void os_changeThreadPriority(Thread* thread, int newPriority) { FASTIVA_LATE_IMPL(); #if 0 if (newPriority < 1 || newPriority > 10) { ALOGW("bad priority %d", newPriority); newPriority = 5; } int newNice = kNiceValues[newPriority-1]; pid_t pid = thread->systemTid; if (newNice >= ANDROID_PRIORITY_BACKGROUND) { set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND); } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) { set_sched_policy(dvmGetSysThreadId(), SP_FOREGROUND); } if (setpriority(PRIO_PROCESS, pid, newNice) != 0) { std::string threadName(dvmGetThreadName(thread)); ALOGI("setPriority(%d) '%s' to prio=%d(n=%d) failed: %s", pid, threadName.c_str(), newPriority, newNice, strerror(errno)); } else { ALOGV("setPriority(%d) to prio=%d(n=%d)", pid, newPriority, newNice); } #endif }
static void printWaitMessage(const DebugOutputTarget* target, const char* detail, Object* obj, Thread* thread) { std::string msg(StringPrintf(" - waiting %s <%p> ", detail, obj)); if (obj->clazz != gDvm.classJavaLangClass) { // I(16573) - waiting on <0xf5feda38> (a java.util.LinkedList) // I(16573) - waiting on <0xf5ed54f8> (a java.lang.Class<java.lang.ref.ReferenceQueue>) msg += "(a " + dvmHumanReadableType(obj) + ")"; } if (thread != NULL) { std::string threadName(dvmGetThreadName(thread)); StringAppendF(&msg, " held by tid=%d (%s)", thread->threadId, threadName.c_str()); } dvmPrintDebugMessage(target, "%s\n", msg.c_str()); }
static void logContentionEvent(Thread *self, u4 waitMs, u4 samplePercent, const char *ownerFileName, u4 ownerLineNumber) { const StackSaveArea *saveArea; const Method *meth; u4 relativePc; char eventBuffer[174]; const char *fileName; char procName[33]; char *cp; size_t len; int fd; /* When a thread is being destroyed it is normal that the frame depth is zero */ if (self->interpSave.curFrame == NULL) { return; } saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame); meth = saveArea->method; cp = eventBuffer; /* Emit the event list length, 1 byte. */ *cp++ = 9; /* Emit the process name, <= 37 bytes. */ fd = open("/proc/self/cmdline", O_RDONLY); memset(procName, 0, sizeof(procName)); read(fd, procName, sizeof(procName) - 1); close(fd); len = strlen(procName); cp = logWriteString(cp, procName, len); /* Emit the sensitive thread ("main thread") status, 5 bytes. */ bool isSensitive = false; if (gDvm.isSensitiveThreadHook != NULL) { isSensitive = gDvm.isSensitiveThreadHook(); } cp = logWriteInt(cp, isSensitive); /* Emit self thread name string, <= 37 bytes. */ std::string selfName = dvmGetThreadName(self); cp = logWriteString(cp, selfName.c_str(), selfName.size()); /* Emit the wait time, 5 bytes. */ cp = logWriteInt(cp, waitMs); /* Emit the source code file name, <= 37 bytes. */ fileName = dvmGetMethodSourceFile(meth); if (fileName == NULL) fileName = ""; cp = logWriteString(cp, fileName, strlen(fileName)); /* Emit the source code line number, 5 bytes. */ relativePc = saveArea->xtra.currentPc - saveArea->method->insns; cp = logWriteInt(cp, dvmLineNumFromPC(meth, relativePc)); /* Emit the lock owner source code file name, <= 37 bytes. */ if (ownerFileName == NULL) { ownerFileName = ""; } else if (strcmp(fileName, ownerFileName) == 0) { /* Common case, so save on log space. */ ownerFileName = "-"; } cp = logWriteString(cp, ownerFileName, strlen(ownerFileName)); /* Emit the source code line number, 5 bytes. */ cp = logWriteInt(cp, ownerLineNumber); /* Emit the sample percentage, 5 bytes. */ cp = logWriteInt(cp, samplePercent); assert((size_t)(cp - eventBuffer) <= sizeof(eventBuffer)); android_btWriteLog(EVENT_LOG_TAG_dvm_lock_sample, EVENT_TYPE_LIST, eventBuffer, (size_t)(cp - eventBuffer)); }
/* * 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; /* * The "currentPc" is updated whenever we execute an instruction that * might throw an exception. Show it here. */ if (framePtr != NULL && !dvmIsBreakFrame(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(framePtr)) { //dvmPrintDebugMessage(target, " (break frame)\n"); } else { int relPc; if (currentPc != NULL) relPc = currentPc - saveArea->method->insns; else relPc = -1; char* className = dvmDescriptorToDot(method->clazz->descriptor); if (dvmIsNativeMethod(method)) dvmPrintDebugMessage(target, " at %s.%s(Native Method)\n", className, method->name); else { dvmPrintDebugMessage(target, " at %s.%s(%s:%s%d)\n", className, method->name, dvmGetMethodSourceFile(method), (relPc >= 0 && first) ? "~" : "", relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc)); } free(className); 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) { className = dvmDescriptorToDot(obj->clazz->descriptor); dvmPrintDebugMessage(target, " - waiting on <%p> (a %s)\n", obj, className); free(className); } } else if (thread->status == THREAD_MONITOR) { Object* obj; Thread* owner; if (extractMonitorEnterObject(thread, &obj, &owner)) { className = dvmDescriptorToDot(obj->clazz->descriptor); if (owner != NULL) { char* threadName = dvmGetThreadName(owner); dvmPrintDebugMessage(target, " - waiting to lock <%p> (a %s) held by threadid=%d (%s)\n", obj, className, owner->threadId, threadName); free(threadName); } else { dvmPrintDebugMessage(target, " - waiting to lock <%p> (a %s) held by ???\n", obj, className); } free(className); } } } } /* * 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) { LOGW("Warning: loop in stack trace at frame %d (%p -> %p)\n", checkCount, framePtr, saveArea->prevFrame); break; } framePtr = saveArea->prevFrame; checkCount++; if (checkCount > 300) { dvmPrintDebugMessage(target, " ***** printed %d frames, not showing any more\n", checkCount); break; } } dvmPrintDebugMessage(target, "\n"); }