eventhelper.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,130 行 · 第 1/3 页
C
1,130 行
(void)outStream_writeObjectRef(env, out, evinfo->thread); (void)outStream_writeByte(out, classTag); (void)outStream_writeObjectRef(env, out, evinfo->clazz); (void)outStream_writeString(out, signature); (void)outStream_writeInt(out, map2jdwpClassStatus(status)); jvmtiDeallocate(signature);}static void writeVMDeathEvent(JNIEnv *env, PacketOutputStream *out, EventInfo *evinfo){}static void handleEventCommandSingle(JNIEnv *env, PacketOutputStream *out, EventCommandSingle *command){ EventInfo *evinfo = &command->info; (void)outStream_writeByte(out, eventIndex2jdwp(evinfo->ei)); (void)outStream_writeInt(out, command->id); switch (evinfo->ei) { case EI_SINGLE_STEP: writeSingleStepEvent(env, out, evinfo); break; case EI_BREAKPOINT: writeBreakpointEvent(env, out, evinfo); break; case EI_FIELD_ACCESS: writeFieldAccessEvent(env, out, evinfo); break; case EI_FIELD_MODIFICATION: writeFieldModificationEvent(env, out, evinfo); break; case EI_EXCEPTION: writeExceptionEvent(env, out, evinfo); break; case EI_THREAD_START: case EI_THREAD_END: writeThreadEvent(env, out, evinfo); break; case EI_CLASS_LOAD: case EI_CLASS_PREPARE: writeClassEvent(env, out, evinfo); break; case EI_MONITOR_CONTENDED_ENTER: case EI_MONITOR_CONTENDED_ENTERED: case EI_MONITOR_WAIT: case EI_MONITOR_WAITED: writeMonitorEvent(env, out, evinfo); break; case EI_VM_DEATH: writeVMDeathEvent(env, out, evinfo); break; default: EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,"unknown event index"); break; } tossEventInfoRefs(env, evinfo);}static void handleUnloadCommandSingle(JNIEnv* env, PacketOutputStream *out, UnloadCommandSingle *command) { (void)outStream_writeByte(out, JDWP_EVENT(CLASS_UNLOAD)); (void)outStream_writeInt(out, command->id); (void)outStream_writeString(out, command->classSignature); jvmtiDeallocate(command->classSignature); command->classSignature = NULL;}static void handleFrameEventCommandSingle(JNIEnv* env, PacketOutputStream *out, FrameEventCommandSingle *command) { if (command->typeKey) { (void)outStream_writeByte(out, JDWP_EVENT(METHOD_EXIT_WITH_RETURN_VALUE)); } else { (void)outStream_writeByte(out, eventIndex2jdwp(command->ei)); } (void)outStream_writeInt(out, command->id); (void)outStream_writeObjectRef(env, out, command->thread); writeCodeLocation(out, command->clazz, command->method, command->location); if (command->typeKey) { (void)outStream_writeValue(env, out, command->typeKey, command->returnValue); if (isObjectTag(command->typeKey) && command->returnValue.l != NULL) { tossGlobalRef(env, &(command->returnValue.l)); } } tossGlobalRef(env, &(command->thread)); tossGlobalRef(env, &(command->clazz));}static voidsuspendWithInvokeEnabled(jbyte policy, jthread thread){ invoker_enableInvokeRequests(thread); if (policy == JDWP_SUSPEND_POLICY(ALL)) { (void)threadControl_suspendAll(); } else { (void)threadControl_suspendThread(thread, JNI_FALSE); }}static voidhandleReportEventCompositeCommand(JNIEnv *env, ReportEventCompositeCommand *recc) { PacketOutputStream out; jint count = recc->eventCount; jint i; if (recc->suspendPolicy != JDWP_SUSPEND_POLICY(NONE)) { /* must determine thread to interrupt before writing */ /* since writing destroys it */ jthread thread = NULL; for (i = 0; i < count; i++) { CommandSingle *single = &(recc->singleCommand[i]); switch (single->singleKind) { case COMMAND_SINGLE_EVENT: thread = single->u.eventCommand.info.thread; break; case COMMAND_SINGLE_FRAME_EVENT: thread = single->u.frameEventCommand.thread; break; } if (thread != NULL) { break; } } if (thread == NULL) { (void)threadControl_suspendAll(); } else { suspendWithInvokeEnabled(recc->suspendPolicy, thread); } } outStream_initCommand(&out, uniqueID(), 0x0, JDWP_COMMAND_SET(Event), JDWP_COMMAND(Event, Composite)); (void)outStream_writeByte(&out, recc->suspendPolicy); (void)outStream_writeInt(&out, count); for (i = 0; i < count; i++) { CommandSingle *single = &(recc->singleCommand[i]); switch (single->singleKind) { case COMMAND_SINGLE_EVENT: handleEventCommandSingle(env, &out, &single->u.eventCommand); break; case COMMAND_SINGLE_UNLOAD: handleUnloadCommandSingle(env, &out, &single->u.unloadCommand); break; case COMMAND_SINGLE_FRAME_EVENT: handleFrameEventCommandSingle(env, &out, &single->u.frameEventCommand); break; } } outStream_sendCommand(&out); outStream_destroy(&out);}static voidhandleReportInvokeDoneCommand(JNIEnv* env, ReportInvokeDoneCommand *command) { invoker_completeInvokeRequest(command->thread); tossGlobalRef(env, &(command->thread));}static voidhandleReportVMInitCommand(JNIEnv* env, ReportVMInitCommand *command) { PacketOutputStream out; if (command->suspendPolicy == JDWP_SUSPEND_POLICY(ALL)) { (void)threadControl_suspendAll(); } else if (command->suspendPolicy == JDWP_SUSPEND_POLICY(EVENT_THREAD)) { (void)threadControl_suspendThread(command->thread, JNI_FALSE); } outStream_initCommand(&out, uniqueID(), 0x0, JDWP_COMMAND_SET(Event), JDWP_COMMAND(Event, Composite)); (void)outStream_writeByte(&out, command->suspendPolicy); (void)outStream_writeInt(&out, 1); /* Always one component */ (void)outStream_writeByte(&out, JDWP_EVENT(VM_INIT)); (void)outStream_writeInt(&out, 0); /* Not in response to an event req. */ (void)outStream_writeObjectRef(env, &out, command->thread); outStream_sendCommand(&out); outStream_destroy(&out); /* Why aren't we tossing this: tossGlobalRef(env, &(command->thread)); */}static voidhandleSuspendThreadCommand(JNIEnv* env, SuspendThreadCommand *command) { /* * For the moment, there's nothing that can be done with the * return code, so we don't check it here. */ (void)threadControl_suspendThread(command->thread, JNI_TRUE); tossGlobalRef(env, &(command->thread));}static voidhandleCommand(JNIEnv *env, HelperCommand *command){ switch (command->commandKind) { case COMMAND_REPORT_EVENT_COMPOSITE: handleReportEventCompositeCommand(env, &command->u.reportEventComposite); break; case COMMAND_REPORT_INVOKE_DONE: handleReportInvokeDoneCommand(env, &command->u.reportInvokeDone); break; case COMMAND_REPORT_VM_INIT: handleReportVMInitCommand(env, &command->u.reportVMInit); break; case COMMAND_SUSPEND_THREAD: handleSuspendThreadCommand(env, &command->u.suspendThread); break; default: EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,"Event Helper Command"); break; }}/* * There was an assumption that only one event with a suspend-all * policy could be processed by commandLoop() at one time. It was * assumed that native thread suspension from the first suspend-all * event would prevent the second suspend-all event from making it * into the command queue. For the Classic VM, this was a reasonable * assumption. However, in HotSpot all thread suspension requires a * VM operation and VM operations take time. * * The solution is to add a mechanism to prevent commandLoop() from * processing more than one event with a suspend-all policy. This is * accomplished by forcing commandLoop() to wait for either * ThreadReferenceImpl.c: resume() or VirtualMachineImpl.c: resume() * when an event with a suspend-all policy has been completed. */static jboolean blockCommandLoop = JNI_FALSE;/* * We wait for either ThreadReferenceImpl.c: resume() or * VirtualMachineImpl.c: resume() to be called. */static voiddoBlockCommandLoop(void) { debugMonitorEnter(blockCommandLoopLock); while (blockCommandLoop == JNI_TRUE) { debugMonitorWait(blockCommandLoopLock); } debugMonitorExit(blockCommandLoopLock);}/* * If the command that we are about to execute has a suspend-all * policy, then prepare for either ThreadReferenceImpl.c: resume() * or VirtualMachineImpl.c: resume() to be called. */static jbooleanneedBlockCommandLoop(HelperCommand *cmd) { if (cmd->commandKind == COMMAND_REPORT_EVENT_COMPOSITE && cmd->u.reportEventComposite.suspendPolicy == JDWP_SUSPEND_POLICY(ALL)) { debugMonitorEnter(blockCommandLoopLock); blockCommandLoop = JNI_TRUE; debugMonitorExit(blockCommandLoopLock); return JNI_TRUE; } return JNI_FALSE;}/* * Used by either ThreadReferenceImpl.c: resume() or * VirtualMachineImpl.c: resume() to resume commandLoop(). */voidunblockCommandLoop(void) { debugMonitorEnter(blockCommandLoopLock); blockCommandLoop = JNI_FALSE; debugMonitorNotifyAll(blockCommandLoopLock); debugMonitorExit(blockCommandLoopLock);}/* * The event helper thread. Dequeues commands and processes them. */static void JNICALLcommandLoop(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg){ LOG_MISC(("Begin command loop thread")); while (JNI_TRUE) { HelperCommand *command = dequeueCommand(); if (command != NULL) { /* * Setup for a potential doBlockCommand() call before calling * handleCommand() to prevent any races. */ jboolean doBlock = needBlockCommandLoop(command); log_debugee_location("commandLoop(): command being handled", NULL, NULL, 0); handleCommand(jni_env, command); completeCommand(command); /* if we just finished a suspend-all cmd, then we block here */ if (doBlock) { doBlockCommandLoop(); } } else { JDI_ASSERT(shutdownEvents); break; } } /* This loop never ends, even as connections come and go with server=y */}void eventHelper_initialize(jbyte sessionID){ jvmtiStartFunction func; currentSessionID = sessionID; holdEvents = JNI_FALSE; shutdownEvents = JNI_FALSE; commandQueue.head = NULL; commandQueue.tail = NULL; commandQueueLock = debugMonitorCreate("JDWP Event Helper Queue Monitor"); commandCompleteLock = debugMonitorCreate("JDWP Event Helper Completion Monitor"); blockCommandLoopLock = debugMonitorCreate("JDWP Event Block CommandLoop Monitor"); /* Start the event handler thread */ func = &commandLoop; (void)spawnNewThread(func, NULL, "JDWP Event Helper Thread");}void eventHelper_reset(jbyte newSessionID){ debugMonitorEnter(commandQueueLock); currentSessionID = newSessionID; holdEvents = JNI_FALSE; debugMonitorNotifyAll(commandQueueLock); debugMonitorExit(commandQueueLock);}voideventHelper_shutdown(void){ debugMonitorEnter(commandQueueLock); holdEvents = JNI_FALSE; shutdownEvents = JNI_TRUE; debugMonitorNotifyAll(commandQueueLock); debugMonitorExit(commandQueueLock);}/* * Provide a means for threadControl to ensure that crucial locks are not * held by suspended threads. */void eventHelper_lock(void){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?