static void notifyTransportError(void) { debugMonitorEnter(cmdQueueLock); transportError = JNI_TRUE; debugMonitorNotify(cmdQueueLock); debugMonitorExit(cmdQueueLock); }
jint transport_sendPacket(jdwpPacket *packet) { jdwpTransportError err = JDWPTRANSPORT_ERROR_NONE; jint rc = 0; if (transport != NULL) { if ( (*transport)->IsOpen(transport) ) { debugMonitorEnter(sendLock); err = (*transport)->WritePacket(transport, packet); debugMonitorExit(sendLock); } if (err != JDWPTRANSPORT_ERROR_NONE) { if ((*transport)->IsOpen(transport)) { printLastError(transport, err); } /* * The users of transport_sendPacket except 0 for * success; non-0 otherwise. */ rc = (jint)-1; } } /* else, bit bucket */ return rc; }
static void enqueue(jdwpPacket *packet) { struct PacketList *pL; struct PacketList *walker; pL = jvmtiAllocate((jint)sizeof(struct PacketList)); if (pL == NULL) { EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"packet list"); } pL->packet = *packet; pL->next = NULL; debugMonitorEnter(cmdQueueLock); if (cmdQueue == NULL) { cmdQueue = pL; debugMonitorNotify(cmdQueueLock); } else { walker = (struct PacketList *)cmdQueue; while (walker->next != NULL) walker = walker->next; walker->next = pL; } debugMonitorExit(cmdQueueLock); }
/* Release tracking of an object by ID */ void commonRef_release(JNIEnv *env, jlong id) { debugMonitorEnter(gdata->refLock); { deleteNodeByID(env, id, 1); } debugMonitorExit(gdata->refLock); }
/* * Given an object ID obtained from the debugger front end, return a * strong, global reference to that object (or NULL if the object * has been collected). The reference can then be used for JNI and * JVMTI calls. Caller is resposible for deleting the returned reference. */ jobject commonRef_idToRef(JNIEnv *env, jlong id) { jobject ref; ref = NULL; debugMonitorEnter(gdata->refLock); { RefNode *node; node = findNodeByID(env, id); if (node != NULL) { if (node->isStrong) { saveGlobalRef(env, node->ref, &ref); } else { jobject lref; lref = JNI_FUNC_PTR(env,NewLocalRef)(env, node->ref); if ( lref == NULL ) { /* Object was GC'd shortly after we found the node */ deleteNodeByID(env, node->seqNum, ALL_REFS); } else { saveGlobalRef(env, node->ref, &ref); JNI_FUNC_PTR(env,DeleteLocalRef)(env, lref); } } } } debugMonitorExit(gdata->refLock); return ref; }
void commonRef_releaseMultiple(JNIEnv *env, jlong id, jint refCount) { debugMonitorEnter(gdata->refLock); { deleteNodeByID(env, id, refCount); } debugMonitorExit(gdata->refLock); }
/* * Used by either ThreadReferenceImpl.c: resume() or * VirtualMachineImpl.c: resume() to resume commandLoop(). */ void unblockCommandLoop(void) { debugMonitorEnter(blockCommandLoopLock); blockCommandLoop = JNI_FALSE; debugMonitorNotifyAll(blockCommandLoopLock); debugMonitorExit(blockCommandLoopLock); }
/* * Given a reference obtained from JNI or JVMTI, return an object * id suitable for sending to the debugger front end. The original * reference is not deleted. */ jlong commonRef_refToID(jobject ref) { JNIEnv *env; RefNode *node; jlong id; if (ref == NULL) { return NULL_OBJECT_ID; } env = getEnv(); debugMonitorEnter(refLock); node = findNodeByRef(env, ref); if (node == NULL) { node = newCommonRef(env, ref); } else { node->count++; } id = OBJECT_ID(node); debugMonitorExit(refLock); return id; }
void eventHelper_releaseEvents(void) { debugMonitorEnter(commandQueueLock); holdEvents = JNI_FALSE; debugMonitorNotifyAll(commandQueueLock); debugMonitorExit(commandQueueLock); }
/* Prevent garbage collection of an object */ jvmtiError commonRef_pin(jlong id) { JNIEnv *env = getEnv(); jvmtiError error = JVMTI_ERROR_NONE; RefNode *node; if (id == NULL_OBJECT_ID) { return JNI_FALSE; } debugMonitorEnter(refLock); node = findNodeByID(env, id); if (node == NULL) { error = JVMTI_ERROR_INVALID_OBJECT; } else { jobject strongRef = strengthenNode(env, node); if (strongRef == NULL) { /* * Referent has been collected, clean up now. */ error = JVMTI_ERROR_INVALID_OBJECT; deleteNodeByID(env, id, ALL_REFS); } } debugMonitorExit(refLock); return error; }
/* * Given a reference obtained from JNI or JVMTI, return an object * id suitable for sending to the debugger front end. */ jlong commonRef_refToID(JNIEnv *env, jobject ref) { jlong id; if (ref == NULL) { return NULL_OBJECT_ID; } id = NULL_OBJECT_ID; debugMonitorEnter(gdata->refLock); { RefNode *node; node = findNodeByRef(env, ref); if (node == NULL) { node = newCommonRef(env, ref); if ( node != NULL ) { id = node->seqNum; } } else { id = node->seqNum; node->count++; } } debugMonitorExit(gdata->refLock); return id; }
/* Reset the commonRefs usage */ void commonRef_reset(JNIEnv *env) { debugMonitorEnter(gdata->refLock); { int i; for (i = 0; i < gdata->objectsByIDsize; i++) { RefNode *node; node = gdata->objectsByID[i]; while (node != NULL) { RefNode *next; next = node->next; deleteNode(env, node); node = next; } gdata->objectsByID[i] = NULL; } /* Toss entire hash table and re-create a new one */ jvmtiDeallocate(gdata->objectsByID); gdata->objectsByID = NULL; gdata->nextSeqNum = 1; /* 0 used for error indication */ initializeObjectsByID(HASH_INIT_SIZE); } debugMonitorExit(gdata->refLock); }
static void enqueueCommand(HelperCommand *command, jboolean wait, jboolean reportingVMDeath) { static jboolean vmDeathReported = JNI_FALSE; CommandQueue *queue = &commandQueue; jint size = commandSize(command); command->done = JNI_FALSE; command->waiting = wait; command->next = NULL; debugMonitorEnter(commandQueueLock); while (size + currentQueueSize > maxQueueSize) { debugMonitorWait(commandQueueLock); } log_debugee_location("enqueueCommand(): HelperCommand being processed", NULL, NULL, 0); if (vmDeathReported) { /* send no more events after VMDeath and don't wait */ wait = JNI_FALSE; } else { currentQueueSize += size; if (queue->head == NULL) { queue->head = command; } else { queue->tail->next = command; } queue->tail = command; if (reportingVMDeath) { vmDeathReported = JNI_TRUE; } } debugMonitorNotifyAll(commandQueueLock); debugMonitorExit(commandQueueLock); if (wait) { debugMonitorEnter(commandCompleteLock); while (!command->done) { log_debugee_location("enqueueCommand(): HelperCommand wait", NULL, NULL, 0); debugMonitorWait(commandCompleteLock); } freeCommand(command); debugMonitorExit(commandCompleteLock); } }
/* * We wait for either ThreadReferenceImpl.c: resume() or * VirtualMachineImpl.c: resume() to be called. */ static void doBlockCommandLoop(void) { debugMonitorEnter(blockCommandLoopLock); while (blockCommandLoop == JNI_TRUE) { debugMonitorWait(blockCommandLoopLock); } debugMonitorExit(blockCommandLoopLock); }
/* * Wait for all initialization to complete. */ void debugInit_waitInitComplete(void) { debugMonitorEnter(initMonitor); while (!initComplete) { debugMonitorWait(initMonitor); } debugMonitorExit(initMonitor); }
void eventHelper_reset(jbyte newSessionID) { debugMonitorEnter(commandQueueLock); currentSessionID = newSessionID; holdEvents = JNI_FALSE; debugMonitorNotifyAll(commandQueueLock); debugMonitorExit(commandQueueLock); }
void commonRef_release(jlong id) { JNIEnv *env = getEnv(); debugMonitorEnter(refLock); deleteNodeByID(env, id, 1); debugMonitorExit(refLock); }
void commonRef_releaseMultiple(jlong id, jint refCount) { JNIEnv *env = getEnv(); debugMonitorEnter(refLock); deleteNodeByID(env, id, refCount); debugMonitorExit(refLock); }
static void signalInitComplete(void) { /* * Initialization is complete */ LOG_MISC(("signal initialization complete")); debugMonitorEnter(initMonitor); initComplete = JNI_TRUE; debugMonitorNotifyAll(initMonitor); debugMonitorExit(initMonitor); }
/* * 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 jboolean needBlockCommandLoop(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; }
static void completeCommand(HelperCommand *command) { if (command->waiting) { debugMonitorEnter(commandCompleteLock); command->done = JNI_TRUE; log_debugee_location("completeCommand(): HelperCommand done waiting", NULL, NULL, 0); debugMonitorNotifyAll(commandCompleteLock); debugMonitorExit(commandCompleteLock); } else { freeCommand(command); } }
static HelperCommand * dequeueCommand(void) { HelperCommand *command = NULL; CommandQueue *queue = &commandQueue; jint size; debugMonitorEnter(commandQueueLock); while (command == NULL) { while (holdEvents || (queue->head == NULL)) { debugMonitorWait(commandQueueLock); } JDI_ASSERT(queue->head); command = queue->head; queue->head = command->next; if (queue->tail == command) { queue->tail = NULL; } log_debugee_location("dequeueCommand(): command being dequeued", NULL, NULL, 0); size = commandSize(command); /* * Immediately close out any commands enqueued from a * previously attached debugger. */ if (command->sessionID != currentSessionID) { log_debugee_location("dequeueCommand(): command session removal", NULL, NULL, 0); completeCommand(command); command = NULL; } /* * There's room in the queue for more. */ currentQueueSize -= size; debugMonitorNotifyAll(commandQueueLock); } debugMonitorExit(commandQueueLock); return command; }
/* * Given an object ID obtained from the debugger front end, return a * strong, global reference to that object (or NULL if the object * has been collected). The reference can then be used for JNI and * JVMTI calls. Caller is resposible for deleting the returned reference. */ jobject commonRef_idToRef(jlong id) { JNIEnv *env = getEnv(); jobject ref = NULL; RefNode *node; debugMonitorEnter(refLock); node = findNodeByID(env, id); if (node != NULL) { saveGlobalRef(env, node->ref, &ref); } debugMonitorExit(refLock); return ref; }
/* Get rid of RefNodes for objects that no longer exist */ void commonRef_compact(void) { JNIEnv *env; RefNode *node; RefNode *prev; int i; env = getEnv(); debugMonitorEnter(gdata->refLock); { if ( gdata->objectsByIDsize > 0 ) { /* * Walk through the id-based hash table. Detach any nodes * for which the ref has been collected. */ for (i = 0; i < gdata->objectsByIDsize; i++) { node = gdata->objectsByID[i]; prev = NULL; while (node != NULL) { /* Has the object been collected? */ if ( (!node->isStrong) && isSameObject(env, node->ref, NULL)) { RefNode *freed; /* Detach from the ID list */ if (prev == NULL) { gdata->objectsByID[i] = node->next; } else { prev->next = node->next; } freed = node; node = node->next; deleteNode(env, freed); } else { prev = node; node = node->next; } } } } } debugMonitorExit(gdata->refLock); }
static void connectionInitiated(jdwpTransportEnv *t) { jint isValid = JNI_FALSE; debugMonitorEnter(listenerLock); /* * Don't allow a connection until initialization is complete */ debugInit_waitInitComplete(); /* Are we the first transport to get a connection? */ if (transport == NULL) { transport = t; isValid = JNI_TRUE; } else { if (transport == t) { /* connected with the same transport as before */ isValid = JNI_TRUE; } else { /* * Another transport got a connection - multiple transports * not fully supported yet so shouldn't get here. */ (*t)->Close(t); JDI_ASSERT(JNI_FALSE); } } if (isValid) { debugMonitorNotifyAll(listenerLock); } debugMonitorExit(listenerLock); if (isValid) { debugLoop_run(); } }
void transport_waitForConnection(void) { /* * If the VM is suspended on debugger initialization, we wait * for a connection before continuing. This ensures that all * events are delivered to the debugger. (We might as well do this * this since the VM won't continue until a remote debugger attaches * and resumes it.) If not suspending on initialization, we must * just drop any packets (i.e. events) so that the VM can continue * to run. The debugger may not attach until much later. */ if (debugInit_suspendOnInit()) { debugMonitorEnter(listenerLock); while (transport == NULL) { debugMonitorWait(listenerLock); } debugMonitorExit(listenerLock); } }
/* Permit garbage collection of an object */ jvmtiError commonRef_unpin(jlong id) { JNIEnv *env = getEnv(); jvmtiError error = JVMTI_ERROR_NONE; RefNode *node; debugMonitorEnter(refLock); node = findNodeByID(env, id); if (node != NULL) { jweak weakRef = weakenNode(env, node); if (weakRef == NULL) { error = JVMTI_ERROR_OUT_OF_MEMORY; } } debugMonitorExit(refLock); return error; }
static jboolean dequeue(jdwpPacket *packet) { struct PacketList *node = NULL; debugMonitorEnter(cmdQueueLock); while (!transportError && (cmdQueue == NULL)) { debugMonitorWait(cmdQueueLock); } if (cmdQueue != NULL) { node = (struct PacketList *)cmdQueue; cmdQueue = node->next; } debugMonitorExit(cmdQueueLock); if (node != NULL) { *packet = node->packet; jvmtiDeallocate(node); } return (node != NULL); }
void commonRef_reset(void) { JNIEnv *env = getEnv(); int i; RefNode *node; debugMonitorEnter(refLock); for (i = 0; i < CR_HASH_SLOT_COUNT; i++) { node = objectsByID[i]; while (node != NULL) { RefNode *temp = node->nextByID; deleteNode(env, node); node = temp; } objectsByID[i] = NULL; objectsByRef[i] = NULL; } nextSeqNum = 1; debugMonitorExit(refLock); }
void commonRef_lock(void) { debugMonitorEnter(refLock); }