summaryrefslogtreecommitdiffstats
path: root/dalvik/src/main/native
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commitfdb2704414a9ed92394ada0d1395e4db86889465 (patch)
tree9b591a4a50054274a197f02b3ccb51313681879f /dalvik/src/main/native
downloadlibcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2
Initial Contribution
Diffstat (limited to 'dalvik/src/main/native')
-rw-r--r--dalvik/src/main/native/dalvik_system_TouchDex.cpp278
-rw-r--r--dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.c78
-rw-r--r--dalvik/src/main/native/sub.mk18
3 files changed, 374 insertions, 0 deletions
diff --git a/dalvik/src/main/native/dalvik_system_TouchDex.cpp b/dalvik/src/main/native/dalvik_system_TouchDex.cpp
new file mode 100644
index 0000000..e8b834b
--- /dev/null
+++ b/dalvik/src/main/native/dalvik_system_TouchDex.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Bit of code to wrap DEX force-updating with a fork() call.
+ */
+
+#define LOG_TAG "TouchDex"
+#include "JNIHelp.h"
+
+#include "cutils/properties.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <assert.h>
+#include <errno.h>
+
+#define JAVA_PACKAGE "dalvik/system"
+
+#ifndef HAVE_ANDROID_OS
+# define BASE_DIR "/work/device/out/linux-x86-debug-sim"
+#else
+# define BASE_DIR ""
+#endif
+
+namespace android {
+
+// fwd
+static void logProcStatus(pid_t pid);
+
+
+/*
+ * private static int trampoline(String dexFiles, String bcp)
+ */
+static jint dalvik_system_TouchDex_trampoline(JNIEnv* env,
+ jclass clazz, jstring dexFilesStr, jstring bcpStr)
+{
+#ifndef HAVE_ANDROID_OS
+ /* don't do this on simulator -- gdb goes "funny" in goobuntu */
+ return 0;
+#endif
+
+ const int kMinTimeout = 900; // 90 seconds
+ const char* bcp;
+ const char* dexFiles;
+ static const char* kExecFile = BASE_DIR "/system/bin/dalvikvm";
+ //static const char* kDebugArg =
+ // "-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n";
+ static const char* kBcpArgName = "-Xbootclasspath:";
+ static const char* kClassName = "dalvik.system.TouchDex";
+ static const char* kExecMode = "-Xint";
+ static const int argc = 7;
+ char* bcpArg;
+ const char* argv[argc+1];
+ const char* kVerifyArg;
+ const char* kDexOptArg;
+ int timeoutMult;
+ pid_t pid;
+ struct timeval startWhen, endWhen;
+ char propBuf[PROPERTY_VALUE_MAX];
+ char execModeBuf[PROPERTY_VALUE_MAX + sizeof("-X")];
+ bool verifyJava = true;
+
+ property_get("dalvik.vm.verify-bytecode", propBuf, "");
+ if (strcmp(propBuf, "true") == 0) {
+ verifyJava = true;
+ } else if (strcmp(propBuf, "false") == 0) {
+ verifyJava = false;
+ } else {
+ /* bad value or not defined; use default */
+ }
+
+ if (verifyJava) {
+ kVerifyArg = "-Xverify:all";
+ kDexOptArg = "-Xdexopt:verified";
+ timeoutMult = 11;
+ } else {
+ kVerifyArg = "-Xverify:none";
+ //kDexOptArg = "-Xdexopt:all";
+ kDexOptArg = "-Xdexopt:verified";
+ timeoutMult = 7;
+ }
+
+ property_get("dalvik.vm.execution-mode", propBuf, "");
+ if (strncmp(propBuf, "int:", 4) == 0) {
+ strcpy(execModeBuf, "-X");
+ strcat(execModeBuf, propBuf);
+ kExecMode = execModeBuf;
+ }
+
+ LOGV("TouchDex trampoline forking\n");
+ gettimeofday(&startWhen, NULL);
+
+ /*
+ * Retrieve strings. Note we want to do this *before* the fork() -- bad
+ * idea to perform Java operations in the child process (not all threads
+ * get carried over to the new process).
+ */
+ bcp = env->GetStringUTFChars(bcpStr, NULL);
+ dexFiles = env->GetStringUTFChars(dexFilesStr, NULL);
+ if (bcp == NULL || dexFiles == NULL) {
+ LOGE("Bad values for bcp=%p dexFiles=%p\n", bcp, dexFiles);
+ abort();
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ LOGE("fork failed: %s", strerror(errno));
+ return -1;
+ }
+
+ if (pid == 0) {
+ /* child */
+ char* bcpArg;
+
+ LOGV("TouchDex trampoline in child\n");
+
+ bcpArg = (char*) malloc(strlen(bcp) + strlen(kBcpArgName) +1);
+ strcpy(bcpArg, kBcpArgName);
+ strcat(bcpArg, bcp);
+
+ argv[0] = kExecFile;
+ argv[1] = bcpArg;
+ argv[2] = kVerifyArg;
+ argv[3] = kDexOptArg;
+ argv[4] = kExecMode;
+ argv[5] = kClassName;
+ argv[6] = dexFiles;
+ argv[7] = NULL;
+
+ //LOGI("Calling execv with args:\n");
+ //for (int i = 0; i < argc; i++)
+ // LOGI(" %d: '%s'\n", i, argv[i]);
+
+ execv(kExecFile, (char* const*) argv);
+ free(bcpArg);
+
+ LOGE("execv '%s' failed: %s\n", kExecFile, strerror(errno));
+ exit(1);
+ } else {
+ int cc, count, dexCount, timeout;
+ int result = -1;
+ const char* cp;
+
+ /*
+ * Adjust the timeout based on how many DEX files we have to
+ * process. Larger DEX files take longer, so this is a crude
+ * approximation at best.
+ *
+ * We need this for http://b/issue?id=836771, which can leave us
+ * stuck waiting for a long time even if there is no work to be done.
+ *
+ * This is currently being (ab)used to convert single files, which
+ * sort of spoils the timeout calculation. We establish a minimum
+ * timeout for single apps.
+ *
+ * The timeout calculation doesn't work at all right when a
+ * directory is specified. So the minimum is now a minute. At
+ * this point it's probably safe to just remove the timeout.
+ *
+ * The timeout is in 1/10ths of a second.
+ */
+ dexCount = 1;
+ cp = dexFiles;
+ while (*++cp != '\0') {
+ if (*cp == ':')
+ dexCount++;
+ }
+ timeout = timeoutMult * dexCount;
+ if (timeout < kMinTimeout)
+ timeout = kMinTimeout;
+
+ env->ReleaseStringUTFChars(bcpStr, bcp);
+ env->ReleaseStringUTFChars(dexFilesStr, dexFiles);
+
+
+ LOGD("TouchDex parent waiting for pid=%d (timeout=%.1fs)\n",
+ (int) pid, timeout / 10.0);
+ for (count = 0; count < timeout; count++) {
+ /* waitpid doesn't take a timeout, so poll and sleep */
+ cc = waitpid(pid, &result, WNOHANG);
+ if (cc < 0) {
+ LOGE("waitpid(%d) failed: %s", (int) pid, strerror(errno));
+ return -1;
+ } else if (cc == 0) {
+ usleep(100000); /* 0.1 sec */
+ } else {
+ /* success! */
+ break;
+ }
+ }
+
+ if (count == timeout) {
+ /* note kill(0) returns 0 if the pid is a zombie */
+ LOGE("timed out waiting for %d; kill(0) returns %d\n",
+ (int) pid, kill(pid, 0));
+ logProcStatus(pid);
+ } else {
+ LOGV("TouchDex done after %d iterations (kill(0) returns %d)\n",
+ count, kill(pid, 0));
+ }
+
+ gettimeofday(&endWhen, NULL);
+ long long start = startWhen.tv_sec * 1000000 + startWhen.tv_usec;
+ long long end = endWhen.tv_sec * 1000000 + endWhen.tv_usec;
+
+ LOGI("Dalvik-cache prep: status=0x%04x, finished in %dms\n",
+ result, (int) ((end - start) / 1000));
+
+ if (WIFEXITED(result))
+ return WEXITSTATUS(result);
+ else
+ return result;
+ }
+}
+
+/*
+ * Dump the contents of /proc/<pid>/status to the log file.
+ */
+static void logProcStatus(pid_t pid)
+{
+ char localBuf[256];
+ FILE* fp;
+
+ sprintf(localBuf, "/proc/%d/status", (int) pid);
+ fp = fopen(localBuf, "r");
+ if (fp == NULL) {
+ LOGI("Unable to open '%s'\n", localBuf);
+ return;
+ }
+
+ LOGI("Contents of %s:\n", localBuf);
+ while (true) {
+ fgets(localBuf, sizeof(localBuf), fp);
+ if (ferror(fp) || feof(fp))
+ break;
+ LOGI(" %s", localBuf);
+ }
+
+ fclose(fp);
+}
+
+/*
+ * JNI registration.
+ */
+static JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "trampoline", "(Ljava/lang/String;Ljava/lang/String;)I",
+ (void*) dalvik_system_TouchDex_trampoline },
+};
+
+extern "C" int register_dalvik_system_TouchDex(JNIEnv* env)
+{
+ return jniRegisterNativeMethods(env, JAVA_PACKAGE "/TouchDex",
+ gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
+
diff --git a/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.c b/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.c
new file mode 100644
index 0000000..25235dc
--- /dev/null
+++ b/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "JNIHelp.h"
+
+/*
+ * public static void emptyJniStaticMethod0()
+ *
+ * For benchmarks, a do-nothing JNI method with no arguments.
+ */
+static void emptyJniStaticMethod0(JNIEnv* env, jclass clazz)
+{
+ // This space intentionally left blank.
+}
+
+/*
+ * public static void emptyJniStaticMethod6(int a, int b, int c,
+ * int d, int e, int f)
+ *
+ * For benchmarks, a do-nothing JNI method with six arguments.
+ */
+static void emptyJniStaticMethod6(JNIEnv* env, jclass clazz,
+ int a, int b, int c, int d, int e, int f)
+{
+ // This space intentionally left blank.
+}
+
+/*
+ * public static void emptyJniStaticMethod6L(String a, String[] b,
+ * int[][] c, Object d, Object[] e, Object[][][][] f)
+ *
+ * For benchmarks, a do-nothing JNI method with six arguments.
+ */
+static void emptyJniStaticMethod6L(JNIEnv* env, jclass clazz,
+ jobject a, jarray b, jarray c, jobject d, jarray e, jarray f)
+{
+ // This space intentionally left blank.
+}
+
+/*
+ * JNI registration
+ */
+static JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "emptyJniStaticMethod0", "()V", emptyJniStaticMethod0 },
+ { "emptyJniStaticMethod6", "(IIIIII)V", emptyJniStaticMethod6 },
+ { "emptyJniStaticMethod6L",
+ "(Ljava/lang/String;[Ljava/lang/String;[[I"
+ "Ljava/lang/Object;[Ljava/lang/Object;[[[[Ljava/lang/Object;)V",
+ emptyJniStaticMethod6L },
+};
+
+int register_org_apache_harmony_dalvik_NativeTestTarget(JNIEnv* env)
+{
+ int result = jniRegisterNativeMethods(env,
+ "org/apache/harmony/dalvik/NativeTestTarget",
+ gMethods, NELEM(gMethods));
+ if (result != 0) {
+ /* print warning, but allow to continue */
+ LOGW("WARNING: NativeTestTarget not registered\n");
+ (*env)->ExceptionClear(env);
+ }
+ return 0;
+}
+
diff --git a/dalvik/src/main/native/sub.mk b/dalvik/src/main/native/sub.mk
new file mode 100644
index 0000000..67cca39
--- /dev/null
+++ b/dalvik/src/main/native/sub.mk
@@ -0,0 +1,18 @@
+# This file is included by the top-level libcore Android.mk.
+# It's not a normal makefile, so we don't include CLEAR_VARS
+# or BUILD_*_LIBRARY.
+
+LOCAL_SRC_FILES := \
+ dalvik_system_TouchDex.cpp \
+ org_apache_harmony_dalvik_NativeTestTarget.c
+
+#LOCAL_C_INCLUDES +=
+
+# Any shared/static libs that are listed here must also
+# be listed in libs/nativehelper/Android.mk.
+# TODO: fix this requirement
+
+#LOCAL_SHARED_LIBRARIES +=
+
+#LOCAL_STATIC_LIBRARIES +=
+