/* * void interrupt() * * Interrupt a thread that is waiting (or is about to wait) on a monitor. */ static void Dalvik_java_lang_VMThread_interrupt(const u4* args, JValue* pResult) { Object* thisPtr = (Object*) args[0]; Thread* thread; dvmLockThreadList(NULL); thread = dvmGetThreadFromThreadObject(thisPtr); if (thread != NULL) dvmThreadInterrupt(thread); dvmUnlockThreadList(); RETURN_VOID(); }
/* * void getStatus() * * Gets the Thread status. Result is in VM terms, has to be mapped to * Thread.State by interpreted code. */ static void Dalvik_java_lang_VMThread_getStatus(const u4* args, JValue* pResult) { Object* thisPtr = (Object*) args[0]; Thread* thread; int result; dvmLockThreadList(NULL); thread = dvmGetThreadFromThreadObject(thisPtr); if (thread != NULL) result = thread->status; else result = THREAD_ZOMBIE; // assume it used to exist and is now gone dvmUnlockThreadList(); RETURN_INT(result); }
/* * void setPriority(int newPriority) * * Alter the priority of the specified thread. "newPriority" will range * from Thread.MIN_PRIORITY to Thread.MAX_PRIORITY (1-10), with "normal" * threads at Thread.NORM_PRIORITY (5). */ static void Dalvik_java_lang_VMThread_setPriority(const u4* args, JValue* pResult) { Object* thisPtr = (Object*) args[0]; int newPriority = args[1]; Thread* thread; dvmLockThreadList(NULL); thread = dvmGetThreadFromThreadObject(thisPtr); if (thread != NULL) dvmChangeThreadPriority(thread, newPriority); //dvmDumpAllThreads(false); dvmUnlockThreadList(); RETURN_VOID(); }
/* * boolean isInterrupted() * * Determine if the specified thread has been interrupted. Does not clear * the flag. */ static void Dalvik_java_lang_VMThread_isInterrupted(const u4* args, JValue* pResult) { Object* thisPtr = (Object*) args[0]; Thread* thread; bool interrupted; dvmLockThreadList(NULL); thread = dvmGetThreadFromThreadObject(thisPtr); if (thread != NULL) interrupted = thread->interrupted; else interrupted = false; dvmUnlockThreadList(); RETURN_BOOLEAN(interrupted); }
/* * boolean holdsLock(Object object) * * Returns whether the current thread has a monitor lock on the specific * object. */ static void Dalvik_java_lang_VMThread_holdsLock(const u4* args, JValue* pResult) { Object* thisPtr = (Object*) args[0]; Object* object = (Object*) args[1]; Thread* thread; if (object == NULL) { dvmThrowNullPointerException("object == null"); RETURN_VOID(); } dvmLockThreadList(NULL); thread = dvmGetThreadFromThreadObject(thisPtr); int result = dvmHoldsLock(thread, object); dvmUnlockThreadList(); RETURN_BOOLEAN(result); }
/* * void nameChanged(String newName) * * The name of the target thread has changed. We may need to alert DDMS. */ static void Dalvik_java_lang_VMThread_nameChanged(const u4* args, JValue* pResult) { Object* thisPtr = (Object*) args[0]; StringObject* nameStr = (StringObject*) args[1]; Thread* thread; int threadId = -1; /* get the thread's ID */ dvmLockThreadList(NULL); thread = dvmGetThreadFromThreadObject(thisPtr); if (thread != NULL) threadId = thread->threadId; dvmUnlockThreadList(); dvmDdmSendThreadNameChange(threadId, nameStr); //char* str = dvmCreateCstrFromString(nameStr); //ALOGI("UPDATE: threadid=%d now '%s'", threadId, str); //free(str); RETURN_VOID(); }
/* * Dump stack frames, starting from the specified frame and moving down. * * Each frame holds a pointer to the currently executing method, and the * saved program counter from the caller ("previous" frame). This means * we don't have the PC for the current method on the stack, which is * pretty reasonable since it's in the "PC register" for the VM. Because * exceptions need to show the correct line number we actually *do* have * an updated version in the fame's "xtra.currentPc", but it's unreliable. * * Note "framePtr" could be NULL in rare circumstances. */ static void dumpFrames(const DebugOutputTarget* target, void* framePtr, Thread* thread) { const StackSaveArea* saveArea; const Method* method; int checkCount = 0; const u2* currentPc = NULL; bool first = true; /* * We call functions that require us to be holding the thread list lock. * It's probable that the caller has already done so, but it's not * guaranteed. If it's not locked, lock it now. */ bool needThreadUnlock = dvmTryLockThreadList(); /* * The "currentPc" is updated whenever we execute an instruction that * might throw an exception. Show it here. */ if (framePtr != NULL && !dvmIsBreakFrame((u4*)framePtr)) { saveArea = SAVEAREA_FROM_FP(framePtr); if (saveArea->xtra.currentPc != NULL) currentPc = saveArea->xtra.currentPc; } while (framePtr != NULL) { saveArea = SAVEAREA_FROM_FP(framePtr); method = saveArea->method; if (dvmIsBreakFrame((u4*)framePtr)) { //dvmPrintDebugMessage(target, " (break frame)\n"); } else { int relPc; if (currentPc != NULL) relPc = currentPc - saveArea->method->insns; else relPc = -1; std::string methodName(dvmHumanReadableMethod(method, false)); if (dvmIsNativeMethod(method)) { dvmPrintDebugMessage(target, " at %s(Native Method)\n", methodName.c_str()); } else { dvmPrintDebugMessage(target, " at %s(%s:%s%d)\n", methodName.c_str(), dvmGetMethodSourceFile(method), (relPc >= 0 && first) ? "~" : "", relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc)); } if (first) { /* * Decorate WAIT and MONITOR threads with some detail on * the first frame. * * warning: wait status not stable, even in suspend */ if (thread->status == THREAD_WAIT || thread->status == THREAD_TIMED_WAIT) { Monitor* mon = thread->waitMonitor; Object* obj = dvmGetMonitorObject(mon); if (obj != NULL) { Thread* joinThread = NULL; if (obj->clazz == gDvm.classJavaLangVMThread) { joinThread = dvmGetThreadFromThreadObject(obj); } if (joinThread == NULL) { joinThread = dvmGetObjectLockHolder(obj); } printWaitMessage(target, "on", obj, joinThread); } } else if (thread->status == THREAD_MONITOR) { Object* obj; Thread* owner; if (extractMonitorEnterObject(thread, &obj, &owner)) { printWaitMessage(target, "to lock", obj, owner); } } } } /* * Get saved PC for previous frame. There's no savedPc in a "break" * frame, because that represents native or interpreted code * invoked by the VM. The saved PC is sitting in the "PC register", * a local variable on the native stack. */ currentPc = saveArea->savedPc; first = false; if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) { ALOGW("Warning: loop in stack trace at frame %d (%p -> %p)", checkCount, framePtr, saveArea->prevFrame); break; } framePtr = saveArea->prevFrame; checkCount++; if (checkCount > 300) { dvmPrintDebugMessage(target, " ***** printed %d frames, not showing any more\n", checkCount); break; } } if (needThreadUnlock) { dvmUnlockThreadList(); } }