summaryrefslogtreecommitdiffstats
path: root/vm/Thread.cpp
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2011-10-27 13:05:45 -0700
committerJeff Brown <jeffbrown@google.com>2011-10-27 18:21:46 -0700
commitb1212301d5cffc06907211d243a21d50c4419dc9 (patch)
tree50e8ec8a6e0e5830739c13136083d4cd5414e2dd /vm/Thread.cpp
parent5552e62455d486d19e5986a67ae2545411d50fbe (diff)
downloadandroid_dalvik-b1212301d5cffc06907211d243a21d50c4419dc9.tar.gz
android_dalvik-b1212301d5cffc06907211d243a21d50c4419dc9.tar.bz2
android_dalvik-b1212301d5cffc06907211d243a21d50c4419dc9.zip
Dump stacks for all native threads, not just those in JNI.
Change-Id: I276f5f448f22f8a926cdfc8c93935da687db5d9b
Diffstat (limited to 'vm/Thread.cpp')
-rw-r--r--vm/Thread.cpp189
1 files changed, 144 insertions, 45 deletions
diff --git a/vm/Thread.cpp b/vm/Thread.cpp
index 0404181a2..7a1ee57d2 100644
--- a/vm/Thread.cpp
+++ b/vm/Thread.cpp
@@ -30,6 +30,10 @@
#include <errno.h>
#include <fcntl.h>
+#ifdef HAVE_ANDROID_OS
+#include <dirent.h>
+#endif
+
#if defined(HAVE_PRCTL)
#include <sys/prctl.h>
#endif
@@ -3207,6 +3211,61 @@ const char* dvmGetThreadStatusStr(ThreadStatus status)
}
}
+static void dumpSchedStat(const DebugOutputTarget* target, pid_t tid) {
+#ifdef HAVE_ANDROID_OS
+ /* get some bits from /proc/self/stat */
+ ProcStatData procStatData;
+ if (!dvmGetThreadStats(&procStatData, tid)) {
+ /* failed, use zeroed values */
+ memset(&procStatData, 0, sizeof(procStatData));
+ }
+
+ /* grab the scheduler stats for this thread */
+ char schedstatBuf[64];
+ snprintf(schedstatBuf, sizeof(schedstatBuf), "/proc/self/task/%d/schedstat", tid);
+ int schedstatFd = open(schedstatBuf, O_RDONLY);
+ strcpy(schedstatBuf, "0 0 0"); /* show this if open/read fails */
+ if (schedstatFd >= 0) {
+ ssize_t bytes;
+ bytes = read(schedstatFd, schedstatBuf, sizeof(schedstatBuf) - 1);
+ close(schedstatFd);
+ if (bytes >= 1) {
+ schedstatBuf[bytes - 1] = '\0'; /* remove trailing newline */
+ }
+ }
+
+ /* show what we got */
+ dvmPrintDebugMessage(target,
+ " | schedstat=( %s ) utm=%lu stm=%lu core=%d\n",
+ schedstatBuf, procStatData.utime, procStatData.stime,
+ procStatData.processor);
+#endif
+}
+
+struct SchedulerStats {
+ int policy;
+ int priority;
+ char group[32];
+};
+
+/*
+ * Get scheduler statistics.
+ */
+static void getSchedulerStats(SchedulerStats* stats, pid_t tid) {
+ struct sched_param sp;
+ if (pthread_getschedparam(pthread_self(), &stats->policy, &sp) != 0) {
+ LOGW("Warning: pthread_getschedparam failed");
+ stats->policy = -1;
+ stats->priority = -1;
+ } else {
+ stats->priority = sp.sched_priority;
+ }
+ if (getSchedulerGroup(tid, stats->group, sizeof(stats->group)) == 0 &&
+ stats->group[0] == '\0') {
+ strcpy(stats->group, "default");
+ }
+}
+
/*
* Print information about the specified thread.
*
@@ -3222,12 +3281,8 @@ void dvmDumpThreadEx(const DebugOutputTarget* target, Thread* thread,
StringObject* nameStr;
char* threadName = NULL;
char* groupName = NULL;
- char schedulerGroupBuf[32];
bool isDaemon;
int priority; // java.lang.Thread priority
- int policy; // pthread policy
- struct sched_param sp; // pthread scheduling parameters
- char schedstatBuf[64]; // contents of /proc/[pid]/task/[tid]/schedstat
/*
* Get the java.lang.Thread object. This function gets called from
@@ -3254,17 +3309,6 @@ void dvmDumpThreadEx(const DebugOutputTarget* target, Thread* thread,
priority = dvmGetFieldInt(threadObj, gDvm.offJavaLangThread_priority);
isDaemon = dvmGetFieldBoolean(threadObj, gDvm.offJavaLangThread_daemon);
- if (pthread_getschedparam(pthread_self(), &policy, &sp) != 0) {
- LOGW("Warning: pthread_getschedparam failed");
- policy = -1;
- sp.sched_priority = -1;
- }
- if (getSchedulerGroup(thread->systemTid, schedulerGroupBuf,
- sizeof(schedulerGroupBuf)) == 0 &&
- schedulerGroupBuf[0] == '\0') {
- strcpy(schedulerGroupBuf, "default");
- }
-
/* a null value for group is not expected, but deal with it anyway */
groupObj = (Object*) dvmGetFieldObject(threadObj,
gDvm.offJavaLangThread_group);
@@ -3276,6 +3320,9 @@ void dvmDumpThreadEx(const DebugOutputTarget* target, Thread* thread,
if (groupName == NULL)
groupName = strdup("(null; initializing?)");
+ SchedulerStats schedStats;
+ getSchedulerStats(&schedStats, thread->systemTid);
+
dvmPrintDebugMessage(target,
"\"%s\"%s prio=%d tid=%d %s%s\n",
threadName, isDaemon ? " daemon" : "",
@@ -3293,44 +3340,21 @@ void dvmDumpThreadEx(const DebugOutputTarget* target, Thread* thread,
dvmPrintDebugMessage(target,
" | sysTid=%d nice=%d sched=%d/%d cgrp=%s handle=%d\n",
thread->systemTid, getpriority(PRIO_PROCESS, thread->systemTid),
- policy, sp.sched_priority, schedulerGroupBuf, (int)thread->handle);
+ schedStats.policy, schedStats.priority, schedStats.group, (int)thread->handle);
- /* get some bits from /proc/self/stat */
- ProcStatData procStatData;
- if (!dvmGetThreadStats(&procStatData, thread->systemTid)) {
- /* failed, use zeroed values */
- memset(&procStatData, 0, sizeof(procStatData));
- }
+ dumpSchedStat(target, thread->systemTid);
- /* grab the scheduler stats for this thread */
- snprintf(schedstatBuf, sizeof(schedstatBuf), "/proc/self/task/%d/schedstat",
- thread->systemTid);
- int schedstatFd = open(schedstatBuf, O_RDONLY);
- strcpy(schedstatBuf, "0 0 0"); /* show this if open/read fails */
- if (schedstatFd >= 0) {
- ssize_t bytes;
- bytes = read(schedstatFd, schedstatBuf, sizeof(schedstatBuf) - 1);
- close(schedstatFd);
- if (bytes >= 1) {
- schedstatBuf[bytes-1] = '\0'; /* remove trailing newline */
- }
+ /* grab the native stack, if possible */
+ if (thread->status == THREAD_NATIVE) {
+ dvmDumpNativeStack(target, thread->systemTid);
}
- /* show what we got */
- dvmPrintDebugMessage(target,
- " | schedstat=( %s ) utm=%lu stm=%lu core=%d\n",
- schedstatBuf, procStatData.utime, procStatData.stime,
- procStatData.processor);
-
if (isRunning)
dvmDumpRunningThreadStack(target, thread);
else
dvmDumpThreadStack(target, thread);
- /* grab the native stack, if possible */
- if (thread->status == THREAD_NATIVE) {
- dvmDumpNativeStack(target, thread);
- }
+ dvmPrintDebugMessage(target, "\n");
dvmReleaseTrackedAlloc(threadObj, NULL);
free(threadName);
@@ -3348,6 +3372,57 @@ std::string dvmGetThreadName(Thread* thread) {
return dvmCreateCstrFromString(nameObj);
}
+#ifdef HAVE_ANDROID_OS
+/*
+ * Dumps information about a non-Dalvik thread.
+ */
+static void dumpNativeThread(const DebugOutputTarget* target, pid_t tid) {
+ char path[64];
+ snprintf(path, sizeof(path), "/proc/%d/comm", tid);
+
+ int fd = open(path, O_RDONLY);
+ char name[64];
+ ssize_t n = 0;
+ if (fd >= 0) {
+ n = read(fd, name, sizeof(name) - 1);
+ close(fd);
+ }
+ if (n > 0 && name[n - 1] == '\n') {
+ n -= 1;
+ }
+ if (n <= 0) {
+ strcpy(name, "<no name>");
+ } else {
+ name[n] = '\0';
+ }
+
+ SchedulerStats schedStats;
+ getSchedulerStats(&schedStats, tid);
+
+ dvmPrintDebugMessage(target,
+ "\"%s\" sysTid=%d nice=%d sched=%d/%d cgrp=%s\n",
+ name, tid, getpriority(PRIO_PROCESS, tid),
+ schedStats.policy, schedStats.priority, schedStats.group);
+ dumpSchedStat(target, tid);
+ dvmDumpNativeStack(target, tid);
+
+ dvmPrintDebugMessage(target, "\n");
+}
+
+/*
+ * Returns true if the specified tid is a Dalvik thread.
+ * Assumes the thread list lock is held.
+ */
+static bool isDalvikThread(pid_t tid) {
+ for (Thread* thread = gDvm.threadList; thread != NULL; thread = thread->next) {
+ if (thread->systemTid == tid) {
+ return true;
+ }
+ }
+ return false;
+}
+#endif
+
/*
* Dump all threads to the log file -- just calls dvmDumpAllThreadsEx() with
* an output target.
@@ -3375,7 +3450,7 @@ void dvmDumpAllThreadsEx(const DebugOutputTarget* target, bool grabLock)
#ifdef HAVE_ANDROID_OS
dvmPrintDebugMessage(target,
- "(mutexes: tll=%x tsl=%x tscl=%x ghl=%x)\n",
+ "(mutexes: tll=%x tsl=%x tscl=%x ghl=%x)\n\n",
gDvm.threadListLock.value,
gDvm._threadSuspendLock.value,
gDvm.threadSuspendCountLock.value,
@@ -3395,6 +3470,30 @@ void dvmDumpAllThreadsEx(const DebugOutputTarget* target, bool grabLock)
thread = thread->next;
}
+#ifdef HAVE_ANDROID_OS
+ char path[64];
+ snprintf(path, sizeof(path), "/proc/%d/task", getpid());
+
+ DIR* d = opendir(path);
+ if (d) {
+ dirent de;
+ dirent* result;
+ bool first = true;
+ while (!readdir_r(d, &de, &result) && result) {
+ char* end;
+ pid_t tid = strtol(de.d_name, &end, 10);
+ if (!*end && !isDalvikThread(tid)) {
+ if (first) {
+ dvmPrintDebugMessage(target, "NATIVE THREADS:\n");
+ first = false;
+ }
+ dumpNativeThread(target, tid);
+ }
+ }
+ closedir(d);
+ }
+#endif
+
if (grabLock)
dvmUnlockThreadList();
}