Merge "ART: Use timeout --foreground"
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk
index d8014bd..be1791b 100644
--- a/build/Android.common_test.mk
+++ b/build/Android.common_test.mk
@@ -133,6 +133,7 @@
LOCAL_MODULE_PATH := $(3)
LOCAL_DEX_PREOPT_IMAGE_LOCATION := $(TARGET_CORE_IMG_OUT)
ifneq ($(wildcard $(LOCAL_PATH)/$(2)/main.list),)
+ LOCAL_MIN_SDK_VERSION := 19
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(LOCAL_PATH)/$(2)/main.list --minimal-main-dex
endif
include $(BUILD_JAVA_LIBRARY)
@@ -148,6 +149,7 @@
LOCAL_JAVA_LIBRARIES := $(HOST_TEST_CORE_JARS)
LOCAL_DEX_PREOPT_IMAGE := $(HOST_CORE_IMG_LOCATION)
ifneq ($(wildcard $(LOCAL_PATH)/$(2)/main.list),)
+ LOCAL_MIN_SDK_VERSION := 19
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(LOCAL_PATH)/$(2)/main.list --minimal-main-dex
endif
include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
diff --git a/cmdline/cmdline_parser.h b/cmdline/cmdline_parser.h
index 82c04e7..952be44 100644
--- a/cmdline/cmdline_parser.h
+++ b/cmdline/cmdline_parser.h
@@ -206,7 +206,7 @@
};
load_value_ = []() -> TArg& {
assert(false && "Should not be appending values to ignored arguments");
- return *reinterpret_cast<TArg*>(0); // Blow up.
+ __builtin_trap(); // Blow up.
};
save_value_specified_ = true;
@@ -270,7 +270,7 @@
load_value_ = []() -> TArg& {
assert(false && "No load value function defined");
- return *reinterpret_cast<TArg*>(0); // Blow up.
+ __builtin_trap(); // Blow up.
};
}
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 872fab3..0b2c0b6 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -601,8 +601,7 @@
Fatal(StringPrintf("dex2oat did not finish after %" PRId64 " seconds",
timeout_in_milliseconds_/1000));
} else if (rc != 0) {
- std::string message(StringPrintf("pthread_cond_timedwait failed: %s",
- strerror(errno)));
+ std::string message(StringPrintf("pthread_cond_timedwait failed: %s", strerror(rc)));
Fatal(message.c_str());
}
}
diff --git a/dexdump/Android.bp b/dexdump/Android.bp
index d15bbda..434cb35 100644
--- a/dexdump/Android.bp
+++ b/dexdump/Android.bp
@@ -49,6 +49,9 @@
darwin: {
enabled: false,
},
+ windows: {
+ enabled: true,
+ },
},
}
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index c3fb5fd..0fcd6a5 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -35,7 +35,6 @@
"base/memory_region.cc",
"base/mem_map.cc",
// "base/mem_map_fuchsia.cc", put in target when fuchsia supported by soong
- "base/mem_map_unix.cc",
"base/os_linux.cc",
"base/runtime_debug.cc",
"base/safe_copy.cc",
@@ -50,20 +49,38 @@
],
target: {
android: {
+ srcs: [
+ "base/mem_map_unix.cc",
+ ],
static_libs: [
// ZipArchive support, the order matters here to get all symbols.
"libziparchive",
"libz",
],
+ shared_libs: [
+ "liblog",
+ // For ashmem.
+ "libcutils",
+ // For common macros.
+ "libbase",
+ ],
// Exclude the version script from Darwin host since it's not
// supported by the linker there. That means ASan checks on Darwin
// might trigger ODR violations.
version_script: "libartbase.map",
},
- host: {
+ not_windows: {
+ srcs: [
+ "base/mem_map_unix.cc",
+ ],
shared_libs: [
"libziparchive",
"libz",
+ "liblog",
+ // For ashmem.
+ "libcutils",
+ // For common macros.
+ "libbase",
],
},
linux_glibc: {
@@ -71,17 +88,20 @@
},
windows: {
version_script: "libartbase.map",
+ static_libs: [
+ "libziparchive",
+ "libz",
+ "liblog",
+ // For ashmem.
+ "libcutils",
+ // For common macros.
+ "libbase",
+ ],
+ cflags: ["-Wno-thread-safety"],
},
},
generated_sources: ["art_libartbase_operator_srcs"],
cflags: ["-DBUILDING_LIBART=1"],
- shared_libs: [
- "liblog",
- // For ashmem.
- "libcutils",
- // For common macros.
- "libbase",
- ],
// Utilities used by various ART libs and tools are linked in statically
// here to avoid shared lib dependencies outside the ART APEX. No target
@@ -147,6 +167,14 @@
"libziparchive",
],
export_shared_lib_headers: ["libbase"],
+ target: {
+ windows: {
+ enabled: true,
+ shared: {
+ enabled: false,
+ },
+ },
+ },
}
art_cc_library {
@@ -160,6 +188,14 @@
"libziparchive",
],
export_shared_lib_headers: ["libbase"],
+ target: {
+ windows: {
+ enabled: true,
+ shared: {
+ enabled: false,
+ },
+ },
+ },
}
art_cc_library {
diff --git a/libartbase/base/arena_allocator.cc b/libartbase/base/arena_allocator.cc
index df3deba..0e7f6cc 100644
--- a/libartbase/base/arena_allocator.cc
+++ b/libartbase/base/arena_allocator.cc
@@ -16,7 +16,6 @@
#include "arena_allocator-inl.h"
-#include <sys/mman.h>
#include <algorithm>
#include <cstddef>
@@ -25,6 +24,8 @@
#include <android-base/logging.h>
+#include "mman.h"
+
namespace art {
constexpr size_t kMemoryToolRedZoneBytes = 8;
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc
index f8d6016..9490798 100644
--- a/libartbase/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -19,11 +19,13 @@
#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
+#ifndef _WIN32
#include <sys/wait.h>
+#endif
#include <unistd.h>
// We need dladdr.
-#ifndef __APPLE__
+#if !defined(__APPLE__) && !defined(_WIN32)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#define DEFINED_GNU_SOURCE
@@ -84,6 +86,10 @@
}
std::string GetAndroidRootSafe(std::string* error_msg) {
+#ifdef _WIN32
+ *error_msg = "GetAndroidRootSafe unsupported for Windows.";
+ return "";
+#else
// Prefer ANDROID_ROOT if it's set.
const char* android_dir = getenv("ANDROID_ROOT");
if (android_dir != nullptr) {
@@ -118,6 +124,7 @@
return "";
}
return "/system";
+#endif
}
std::string GetAndroidRoot() {
@@ -179,6 +186,15 @@
void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache,
bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) {
+#ifdef _WIN32
+ UNUSED(subdir);
+ UNUSED(create_if_absent);
+ UNUSED(dalvik_cache);
+ UNUSED(have_android_data);
+ UNUSED(dalvik_cache_exists);
+ UNUSED(is_global_cache);
+ LOG(FATAL) << "GetDalvikCache unsupported on Windows.";
+#else
CHECK(subdir != nullptr);
std::string error_msg;
const char* android_data = GetAndroidDataSafe(&error_msg);
@@ -199,6 +215,7 @@
*dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) &&
(mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST));
}
+#endif
}
std::string GetDalvikCache(const char* subdir) {
@@ -262,9 +279,15 @@
}
bool LocationIsOnSystem(const char* path) {
+#ifdef _WIN32
+ UNUSED(path);
+ LOG(FATAL) << "LocationIsOnSystem is unsupported on Windows.";
+ return false;
+#else
UniqueCPtr<const char[]> full_path(realpath(path, nullptr));
return full_path != nullptr &&
android::base::StartsWith(full_path.get(), GetAndroidRoot().c_str());
+#endif
}
bool LocationIsOnSystemFramework(const char* full_path) {
diff --git a/libartbase/base/malloc_arena_pool.cc b/libartbase/base/malloc_arena_pool.cc
index 02e29f1..4de34b5 100644
--- a/libartbase/base/malloc_arena_pool.cc
+++ b/libartbase/base/malloc_arena_pool.cc
@@ -16,7 +16,6 @@
#include "malloc_arena_pool.h"
-#include <sys/mman.h>
#include <algorithm>
#include <cstddef>
@@ -25,6 +24,7 @@
#include <android-base/logging.h>
#include "arena_allocator-inl.h"
+#include "mman.h"
namespace art {
diff --git a/libartbase/base/mem_map.cc b/libartbase/base/mem_map.cc
index 532ca28..2833750 100644
--- a/libartbase/base/mem_map.cc
+++ b/libartbase/base/mem_map.cc
@@ -18,8 +18,7 @@
#include <inttypes.h>
#include <stdlib.h>
-#include <sys/mman.h> // For the PROT_* and MAP_* constants.
-#if !defined(ANDROID_OS) && !defined(__Fuchsia__)
+#if !defined(ANDROID_OS) && !defined(__Fuchsia__) && !defined(_WIN32)
#include <sys/resource.h>
#endif
@@ -39,6 +38,7 @@
#include "globals.h"
#include "logging.h" // For VLOG_IS_ON.
#include "memory_tool.h"
+#include "mman.h" // For the PROT_* and MAP_* constants.
#include "utils.h"
#ifndef MAP_ANONYMOUS
@@ -811,19 +811,30 @@
if (!kMadviseZeroes) {
memset(base_begin_, 0, base_size_);
}
+#ifdef _WIN32
+ // It is benign not to madvise away the pages here.
+ PLOG(WARNING) << "MemMap::MadviseDontNeedAndZero does not madvise on Windows.";
+#else
int result = madvise(base_begin_, base_size_, MADV_DONTNEED);
if (result == -1) {
PLOG(WARNING) << "madvise failed";
}
+#endif
}
}
bool MemMap::Sync() {
+#ifdef _WIN32
+ // TODO: add FlushViewOfFile support.
+ PLOG(ERROR) << "MemMap::Sync unsupported on Windows.";
+ return false;
+#else
// Historical note: To avoid Valgrind errors, we temporarily lifted the lower-end noaccess
// protection before passing it to msync() when `redzone_size_` was non-null, as Valgrind
// only accepts page-aligned base address, and excludes the higher-end noaccess protection
// from the msync range. b/27552451.
return msync(BaseBegin(), BaseSize(), MS_SYNC) == 0;
+#endif
}
bool MemMap::Protect(int prot) {
@@ -832,10 +843,12 @@
return true;
}
+#ifndef _WIN32
if (mprotect(base_begin_, base_size_, prot) == 0) {
prot_ = prot;
return true;
}
+#endif
PLOG(ERROR) << "mprotect(" << reinterpret_cast<void*>(base_begin_) << ", " << base_size_ << ", "
<< prot << ") failed";
@@ -1206,7 +1219,11 @@
DCHECK_LE(page_begin, page_end);
DCHECK_LE(page_end, mem_end);
std::fill(mem_begin, page_begin, 0);
+#ifdef _WIN32
+ LOG(WARNING) << "ZeroAndReleasePages does not madvise on Windows.";
+#else
CHECK_NE(madvise(page_begin, page_end - page_begin, MADV_DONTNEED), -1) << "madvise failed";
+#endif
std::fill(page_end, mem_end, 0);
}
}
diff --git a/libartbase/base/mem_map_fuchsia.cc b/libartbase/base/mem_map_fuchsia.cc
index d1c92ce..6b0e06c 100644
--- a/libartbase/base/mem_map_fuchsia.cc
+++ b/libartbase/base/mem_map_fuchsia.cc
@@ -15,8 +15,8 @@
*/
#include "mem_map.h"
-#include <sys/mman.h>
#include "logging.h"
+#include "mman.h"
#include <zircon/process.h>
#include <zircon/syscalls.h>
diff --git a/libartbase/base/mem_map_test.cc b/libartbase/base/mem_map_test.cc
index 074d4c2..bf39fd1 100644
--- a/libartbase/base/mem_map_test.cc
+++ b/libartbase/base/mem_map_test.cc
@@ -16,8 +16,6 @@
#include "mem_map.h"
-#include <sys/mman.h>
-
#include <memory>
#include <random>
@@ -25,6 +23,7 @@
#include "common_runtime_test.h" // For TEST_DISABLED_FOR_MIPS
#include "logging.h"
#include "memory_tool.h"
+#include "mman.h"
#include "unix_file/fd_file.h"
namespace art {
diff --git a/libartbase/base/mem_map_unix.cc b/libartbase/base/mem_map_unix.cc
index 601b049..ac854df 100644
--- a/libartbase/base/mem_map_unix.cc
+++ b/libartbase/base/mem_map_unix.cc
@@ -16,7 +16,7 @@
#include "mem_map.h"
-#include <sys/mman.h>
+#include "mman.h"
namespace art {
diff --git a/libartbase/base/membarrier.cc b/libartbase/base/membarrier.cc
index 4c86b6b..abb36bc 100644
--- a/libartbase/base/membarrier.cc
+++ b/libartbase/base/membarrier.cc
@@ -18,8 +18,10 @@
#include <errno.h>
+#if !defined(_WIN32)
#include <sys/syscall.h>
#include <unistd.h>
+#endif
#include "macros.h"
#if defined(__BIONIC__)
diff --git a/libartbase/base/memfd.cc b/libartbase/base/memfd.cc
index 7c20401..780be32 100644
--- a/libartbase/base/memfd.cc
+++ b/libartbase/base/memfd.cc
@@ -18,9 +18,11 @@
#include <errno.h>
#include <stdio.h>
+#if !defined(_WIN32)
#include <sys/syscall.h>
#include <sys/utsname.h>
#include <unistd.h>
+#endif
#include "macros.h"
diff --git a/libartbase/base/mman.h b/libartbase/base/mman.h
new file mode 100644
index 0000000..bd63f65
--- /dev/null
+++ b/libartbase/base/mman.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifndef ART_LIBARTBASE_BASE_MMAN_H_
+#define ART_LIBARTBASE_BASE_MMAN_H_
+
+#ifdef _WIN32
+
+// There is no sys/mman.h in mingw.
+// As these are just placeholders for the APIs, all values are stubbed out.
+
+#define PROT_READ 0 // 0x1
+#define PROT_WRITE 0 // 0x2
+#define PROT_EXEC 0 // 0x4
+#define PROT_NONE 0 // 0x0
+
+#define MAP_SHARED 0 // 0x01
+#define MAP_PRIVATE 0 // 0x02
+
+#define MAP_FAILED nullptr // ((void*) -1)
+#define MAP_FIXED 0 // 0x10
+#define MAP_ANONYMOUS 0 // 0x20
+
+#else
+
+#include <sys/mman.h>
+
+#endif
+
+
+#endif // ART_LIBARTBASE_BASE_MMAN_H_
diff --git a/libartbase/base/os_linux.cc b/libartbase/base/os_linux.cc
index f8b31cf..a00779e 100644
--- a/libartbase/base/os_linux.cc
+++ b/libartbase/base/os_linux.cc
@@ -50,7 +50,12 @@
}
File* OS::CreateEmptyFileWriteOnly(const char* name) {
- return art::CreateEmptyFile(name, O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC);
+#ifdef _WIN32
+ int flags = O_WRONLY | O_TRUNC;
+#else
+ int flags = O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC;
+#endif
+ return art::CreateEmptyFile(name, flags);
}
File* OS::OpenFileWithFlags(const char* name, int flags, bool auto_flush) {
diff --git a/libartbase/base/safe_copy.cc b/libartbase/base/safe_copy.cc
index b46b921..ad75aa7 100644
--- a/libartbase/base/safe_copy.cc
+++ b/libartbase/base/safe_copy.cc
@@ -16,8 +16,10 @@
#include "safe_copy.h"
+#ifdef __linux__
#include <sys/uio.h>
#include <sys/user.h>
+#endif
#include <unistd.h>
#include <algorithm>
diff --git a/libartbase/base/safe_copy_test.cc b/libartbase/base/safe_copy_test.cc
index c23651f..9f7d409 100644
--- a/libartbase/base/safe_copy_test.cc
+++ b/libartbase/base/safe_copy_test.cc
@@ -18,12 +18,12 @@
#include <errno.h>
#include <string.h>
-#include <sys/mman.h>
#include <sys/user.h>
#include "android-base/logging.h"
#include "globals.h"
#include "gtest/gtest.h"
+#include "mman.h"
namespace art {
diff --git a/libartbase/base/scoped_flock.cc b/libartbase/base/scoped_flock.cc
index 2f16fb2..b16a45a 100644
--- a/libartbase/base/scoped_flock.cc
+++ b/libartbase/base/scoped_flock.cc
@@ -35,6 +35,14 @@
/* static */ ScopedFlock LockedFile::Open(const char* filename, int flags, bool block,
std::string* error_msg) {
+#ifdef _WIN32
+ // TODO: implement file locking for Windows.
+ UNUSED(filename);
+ UNUSED(flags);
+ UNUSED(block);
+ *error_msg = "flock is unsupported on Windows";
+ return nullptr;
+#else
while (true) {
// NOTE: We don't check usage here because the ScopedFlock should *never* be
// responsible for flushing its underlying FD. Its only purpose should be
@@ -89,10 +97,19 @@
return ScopedFlock(new LockedFile(std::move((*file.get()))));
}
+#endif
}
ScopedFlock LockedFile::DupOf(const int fd, const std::string& path,
const bool read_only_mode, std::string* error_msg) {
+#ifdef _WIN32
+ // TODO: implement file locking for Windows.
+ UNUSED(fd);
+ UNUSED(path);
+ UNUSED(read_only_mode);
+ *error_msg = "flock is unsupported on Windows.";
+ return nullptr;
+#else
// NOTE: We don't check usage here because the ScopedFlock should *never* be
// responsible for flushing its underlying FD. Its only purpose should be
// to acquire a lock, and the unlock / close in the corresponding
@@ -112,9 +129,11 @@
}
return locked_file;
+#endif
}
void LockedFile::ReleaseLock() {
+#ifndef _WIN32
if (this->Fd() != -1) {
int flock_result = TEMP_FAILURE_RETRY(flock(this->Fd(), LOCK_UN));
if (flock_result != 0) {
@@ -126,6 +145,7 @@
PLOG(WARNING) << "Unable to unlock file " << this->GetPath();
}
}
+#endif
}
} // namespace art
diff --git a/libartbase/base/socket_peer_is_trusted.cc b/libartbase/base/socket_peer_is_trusted.cc
index 440054e..3996d90 100644
--- a/libartbase/base/socket_peer_is_trusted.cc
+++ b/libartbase/base/socket_peer_is_trusted.cc
@@ -16,8 +16,10 @@
#include "socket_peer_is_trusted.h"
+#if !defined(_WIN32)
#include <pwd.h>
#include <sys/socket.h>
+#endif
#include <android-base/logging.h>
diff --git a/libartbase/base/time_utils.cc b/libartbase/base/time_utils.cc
index cb30246..aa6c987 100644
--- a/libartbase/base/time_utils.cc
+++ b/libartbase/base/time_utils.cc
@@ -14,12 +14,14 @@
* limitations under the License.
*/
+#include "time_utils.h"
+
#include <inttypes.h>
+#include <stdio.h>
+
#include <limits>
#include <sstream>
-#include "time_utils.h"
-
#include "android-base/stringprintf.h"
#include "logging.h"
@@ -30,6 +32,20 @@
namespace art {
+namespace {
+
+#if !defined(__linux__)
+int GetTimeOfDay(struct timeval* tv, struct timezone* tz) {
+#ifdef _WIN32
+ return mingw_gettimeofday(tv, tz);
+#else
+ return gettimeofday(tv, tz);
+#endif
+}
+#endif
+
+} // namespace
+
using android::base::StringPrintf;
std::string PrettyDuration(uint64_t nano_duration, size_t max_fraction_digits) {
@@ -117,7 +133,12 @@
std::string GetIsoDate() {
time_t now = time(nullptr);
tm tmbuf;
+#ifdef _WIN32
+ localtime_s(&tmbuf, &now);
+ tm* ptm = &tmbuf;
+#else
tm* ptm = localtime_r(&now, &tmbuf);
+#endif
return StringPrintf("%04d-%02d-%02d %02d:%02d:%02d",
ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
@@ -130,7 +151,7 @@
return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_nsec / UINT64_C(1000000);
#else
timeval now;
- gettimeofday(&now, nullptr);
+ GetTimeOfDay(&now, nullptr);
return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_usec / UINT64_C(1000);
#endif
}
@@ -142,7 +163,7 @@
return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_nsec / UINT64_C(1000);
#else
timeval now;
- gettimeofday(&now, nullptr);
+ GetTimeOfDay(&now, nullptr);
return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_usec;
#endif
}
@@ -154,7 +175,7 @@
return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec;
#else
timeval now;
- gettimeofday(&now, nullptr);
+ GetTimeOfDay(&now, nullptr);
return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_usec * UINT64_C(1000);
#endif
}
@@ -195,12 +216,12 @@
void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts) {
if (absolute) {
-#if !defined(__APPLE__)
+#if defined(__linux__)
clock_gettime(clock, ts);
#else
UNUSED(clock);
timeval tv;
- gettimeofday(&tv, nullptr);
+ GetTimeOfDay(&tv, nullptr);
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
#endif
diff --git a/libartbase/base/time_utils.h b/libartbase/base/time_utils.h
index 431d3e1..15805f3 100644
--- a/libartbase/base/time_utils.h
+++ b/libartbase/base/time_utils.h
@@ -18,6 +18,7 @@
#define ART_LIBARTBASE_BASE_TIME_UTILS_H_
#include <stdint.h>
+#include <stdio.h> // Needed for correct _WIN32 build.
#include <time.h>
#include <string>
diff --git a/libartbase/base/unix_file/fd_file.cc b/libartbase/base/unix_file/fd_file.cc
index 76894c6..8831b9c 100644
--- a/libartbase/base/unix_file/fd_file.cc
+++ b/libartbase/base/unix_file/fd_file.cc
@@ -25,8 +25,13 @@
#include <android/fdsan.h>
#endif
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
#include <limits>
+#include <android-base/file.h>
#include <android-base/logging.h>
// Includes needed for FdFile::Copy().
@@ -40,6 +45,96 @@
namespace unix_file {
+#if defined(_WIN32)
+// RAII wrapper for an event object to allow asynchronous I/O to correctly signal completion.
+class ScopedEvent {
+ public:
+ ScopedEvent() {
+ handle_ = CreateEventA(/*lpEventAttributes*/ nullptr,
+ /*bManualReset*/ true,
+ /*bInitialState*/ false,
+ /*lpName*/ nullptr);
+ }
+
+ ~ScopedEvent() { CloseHandle(handle_); }
+
+ HANDLE handle() { return handle_; }
+
+ private:
+ HANDLE handle_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedEvent);
+};
+
+// Windows implementation of pread/pwrite. Note that these DO move the file descriptor's read/write
+// position, but do so atomically.
+static ssize_t pread(int fd, void* data, size_t byte_count, off64_t offset) {
+ ScopedEvent event;
+ if (event.handle() == INVALID_HANDLE_VALUE) {
+ PLOG(ERROR) << "Could not create event handle.";
+ errno = EIO;
+ return static_cast<ssize_t>(-1);
+ }
+
+ auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+ DWORD bytes_read = 0;
+ OVERLAPPED overlapped = {};
+ overlapped.Offset = static_cast<DWORD>(offset);
+ overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
+ overlapped.hEvent = event.handle();
+ if (!ReadFile(handle, data, static_cast<DWORD>(byte_count), &bytes_read, &overlapped)) {
+ // If the read failed with other than ERROR_IO_PENDING, return an error.
+ // ERROR_IO_PENDING signals the write was begun asynchronously.
+ // Block until the asynchronous operation has finished or fails, and return
+ // result accordingly.
+ if (::GetLastError() != ERROR_IO_PENDING ||
+ !::GetOverlappedResult(handle, &overlapped, &bytes_read, TRUE)) {
+ // In case someone tries to read errno (since this is masquerading as a POSIX call).
+ errno = EIO;
+ return static_cast<ssize_t>(-1);
+ }
+ }
+ return static_cast<ssize_t>(bytes_read);
+}
+
+static ssize_t pwrite(int fd, const void* buf, size_t count, off64_t offset) {
+ ScopedEvent event;
+ if (event.handle() == INVALID_HANDLE_VALUE) {
+ PLOG(ERROR) << "Could not create event handle.";
+ errno = EIO;
+ return static_cast<ssize_t>(-1);
+ }
+
+ auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+ DWORD bytes_written = 0;
+ OVERLAPPED overlapped = {};
+ overlapped.Offset = static_cast<DWORD>(offset);
+ overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
+ overlapped.hEvent = event.handle();
+ if (!::WriteFile(handle, buf, count, &bytes_written, &overlapped)) {
+ // If the write failed with other than ERROR_IO_PENDING, return an error.
+ // ERROR_IO_PENDING signals the write was begun asynchronously.
+ // Block until the asynchronous operation has finished or fails, and return
+ // result accordingly.
+ if (::GetLastError() != ERROR_IO_PENDING ||
+ !::GetOverlappedResult(handle, &overlapped, &bytes_written, TRUE)) {
+ // In case someone tries to read errno (since this is masquerading as a POSIX call).
+ errno = EIO;
+ return static_cast<ssize_t>(-1);
+ }
+ }
+ return static_cast<ssize_t>(bytes_written);
+}
+
+static int fsync(int fd) {
+ auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+ if (handle != INVALID_HANDLE_VALUE && ::FlushFileBuffers(handle)) {
+ return 0;
+ }
+ errno = EINVAL;
+ return -1;
+}
+#endif
+
#if defined(__BIONIC__)
static uint64_t GetFdFileOwnerTag(FdFile* fd_file) {
return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_ART_FDFILE,
diff --git a/libartbase/base/utils.cc b/libartbase/base/utils.cc
index 0f172fd..58d8575 100644
--- a/libartbase/base/utils.cc
+++ b/libartbase/base/utils.cc
@@ -19,9 +19,7 @@
#include <inttypes.h>
#include <pthread.h>
#include <sys/stat.h>
-#include <sys/syscall.h>
#include <sys/types.h>
-#include <sys/wait.h>
#include <unistd.h>
#include <fstream>
@@ -47,6 +45,16 @@
#if defined(__linux__)
#include <linux/unistd.h>
+#include <sys/syscall.h>
+#endif
+
+#if defined(_WIN32)
+#include <windows.h>
+// This include needs to be here due to our coding conventions. Unfortunately
+// it drags in the definition of the dread ERROR macro.
+#ifdef ERROR
+#undef ERROR
+#endif
#endif
namespace art {
@@ -61,6 +69,8 @@
return owner;
#elif defined(__BIONIC__)
return gettid();
+#elif defined(_WIN32)
+ return static_cast<pid_t>(::GetCurrentThreadId());
#else
return syscall(__NR_gettid);
#endif
@@ -68,12 +78,17 @@
std::string GetThreadName(pid_t tid) {
std::string result;
+#ifdef _WIN32
+ UNUSED(tid);
+ result = "<unknown>";
+#else
// TODO: make this less Linux-specific.
if (ReadFileToString(StringPrintf("/proc/self/task/%d/comm", tid), &result)) {
result.resize(result.size() - 1); // Lose the trailing '\n'.
} else {
result = "<unknown>";
}
+#endif
return result;
}
@@ -137,7 +152,7 @@
} else {
s = thread_name + len - 15;
}
-#if defined(__linux__)
+#if defined(__linux__) || defined(_WIN32)
// pthread_setname_np fails rather than truncating long strings.
char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded in the kernel.
strncpy(buf, s, sizeof(buf)-1);
@@ -153,6 +168,11 @@
void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) {
*utime = *stime = *task_cpu = 0;
+#ifdef _WIN32
+ // TODO: implement this.
+ UNUSED(tid);
+ *state = 'S';
+#else
std::string stats;
// TODO: make this less Linux-specific.
if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
@@ -167,6 +187,7 @@
*utime = strtoull(fields[11].c_str(), nullptr, 10);
*stime = strtoull(fields[12].c_str(), nullptr, 10);
*task_cpu = strtoull(fields[36].c_str(), nullptr, 10);
+#endif
}
static void ParseStringAfterChar(const std::string& s,
diff --git a/libartbase/base/zip_archive.cc b/libartbase/base/zip_archive.cc
index a7f4b28..5056edc 100644
--- a/libartbase/base/zip_archive.cc
+++ b/libartbase/base/zip_archive.cc
@@ -18,7 +18,6 @@
#include <fcntl.h>
#include <stdio.h>
-#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -27,6 +26,7 @@
#include "android-base/stringprintf.h"
#include "ziparchive/zip_archive.h"
+#include "base/mman.h"
#include "bit_utils.h"
#include "unix_file/fd_file.h"
@@ -203,6 +203,11 @@
}
static void SetCloseOnExec(int fd) {
+#ifdef _WIN32
+ // Exec is not supported on Windows.
+ UNUSED(fd);
+ PLOG(ERROR) << "SetCloseOnExec is not supported on Windows.";
+#else
// This dance is more portable than Linux's O_CLOEXEC open(2) flag.
int flags = fcntl(fd, F_GETFD);
if (flags == -1) {
@@ -214,6 +219,7 @@
PLOG(WARNING) << "fcntl(" << fd << ", F_SETFD, " << flags << ") failed";
return;
}
+#endif
}
ZipArchive* ZipArchive::Open(const char* filename, std::string* error_msg) {
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 4d6aa5c..a4f7e25 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -43,30 +43,58 @@
"libziparchive",
"libz",
],
+ shared_libs: [
+ // For MemMap.
+ "libartbase",
+ "liblog",
+ // For atrace.
+ "libcutils",
+ // For common macros.
+ "libbase",
+ ],
+ export_shared_lib_headers: [
+ "libartbase",
+ "libbase",
+ ],
},
- host: {
+ not_windows: {
shared_libs: [
"libziparchive",
"libz",
+ // For MemMap.
+ "libartbase",
+ "liblog",
+ // For atrace.
+ "libcutils",
+ // For common macros.
+ "libbase",
],
+ export_shared_lib_headers: [
+ "libartbase",
+ "libbase",
+ ],
+ },
+ windows: {
+ static_libs: [
+ "libziparchive",
+ "libz",
+ // For MemMap.
+ "libartbase",
+ "liblog",
+ // For atrace.
+ "libcutils",
+ // For common macros.
+ "libbase",
+ ],
+ export_static_lib_headers: [
+ "libartbase",
+ "libbase",
+ ],
+ cflags: ["-Wno-thread-safety"],
},
},
generated_sources: ["dexfile_operator_srcs"],
- shared_libs: [
- // For MemMap.
- "libartbase",
- "liblog",
- // For atrace.
- "libcutils",
- // For common macros.
- "libbase",
- "libz",
- ],
export_include_dirs: ["."],
- export_shared_lib_headers: [
- "libartbase",
- "libbase",
- ],
}
cc_defaults {
@@ -121,6 +149,14 @@
strip: {
keep_symbols: true,
},
+ target: {
+ windows: {
+ enabled: true,
+ shared: {
+ enabled: false,
+ },
+ },
+ },
}
art_cc_library {
@@ -129,6 +165,14 @@
"art_debug_defaults",
"libdexfile_defaults",
],
+ target: {
+ windows: {
+ enabled: true,
+ shared: {
+ enabled: false,
+ },
+ },
+ },
}
cc_library_headers {
diff --git a/libdexfile/dex/art_dex_file_loader.cc b/libdexfile/dex/art_dex_file_loader.cc
index ae1322d..57e838f 100644
--- a/libdexfile/dex/art_dex_file_loader.cc
+++ b/libdexfile/dex/art_dex_file_loader.cc
@@ -16,7 +16,6 @@
#include "art_dex_file_loader.h"
-#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include <sys/stat.h>
#include "android-base/stringprintf.h"
@@ -24,6 +23,7 @@
#include "base/file_magic.h"
#include "base/file_utils.h"
#include "base/mem_map.h"
+#include "base/mman.h" // For the PROT_* and MAP_* constants.
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/unix_file/fd_file.h"
diff --git a/libdexfile/dex/dex_file_layout.cc b/libdexfile/dex/dex_file_layout.cc
index 75a3111..929025a 100644
--- a/libdexfile/dex/dex_file_layout.cc
+++ b/libdexfile/dex/dex_file_layout.cc
@@ -16,9 +16,9 @@
#include "dex_file_layout.h"
-#include <sys/mman.h>
#include "base/bit_utils.h"
+#include "base/mman.h"
#include "dex_file.h"
namespace art {
@@ -26,6 +26,12 @@
int DexLayoutSection::MadviseLargestPageAlignedRegion(const uint8_t* begin,
const uint8_t* end,
int advice) {
+#ifdef _WIN32
+ UNUSED(begin);
+ UNUSED(end);
+ UNUSED(advice);
+ PLOG(WARNING) << "madvise is unsupported on Windows.";
+#else
DCHECK_LE(begin, end);
begin = AlignUp(begin, kPageSize);
end = AlignDown(end, kPageSize);
@@ -37,6 +43,7 @@
}
return result;
}
+#endif
return 0;
}
@@ -50,6 +57,11 @@
}
void DexLayoutSections::Madvise(const DexFile* dex_file, MadviseState state) const {
+#ifdef _WIN32
+ UNUSED(dex_file);
+ UNUSED(state);
+ PLOG(WARNING) << "madvise is unsupported on Windows.";
+#else
// The dex file is already defaulted to random access everywhere.
for (const DexLayoutSection& section : sections_) {
switch (state) {
@@ -79,6 +91,7 @@
}
}
}
+#endif
}
std::ostream& operator<<(std::ostream& os, const DexLayoutSection& section) {
diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc
index 1884bcf..a719d41 100644
--- a/libdexfile/dex/dex_file_loader.cc
+++ b/libdexfile/dex/dex_file_loader.cc
@@ -187,12 +187,18 @@
std::string base_location = GetBaseLocation(dex_location);
const char* suffix = dex_location + base_location.size();
DCHECK(suffix[0] == 0 || suffix[0] == kMultiDexSeparator);
+#ifdef _WIN32
+ // Warning: No symbolic link processing here.
+ PLOG(WARNING) << "realpath is unsupported on Windows.";
+#else
// Warning: Bionic implementation of realpath() allocates > 12KB on the stack.
// Do not run this code on a small stack, e.g. in signal handler.
UniqueCPtr<const char[]> path(realpath(base_location.c_str(), nullptr));
if (path != nullptr && path.get() != base_location) {
return std::string(path.get()) + suffix;
- } else if (suffix[0] == 0) {
+ }
+#endif
+ if (suffix[0] == 0) {
return base_location;
} else {
return dex_location;
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index f7f3a8d..3b57b07 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -95,7 +95,8 @@
weak_ref_access_enabled_(true),
copied_live_bytes_ratio_sum_(0.f),
gc_count_(0),
- inter_region_bitmap_(nullptr),
+ region_space_inter_region_bitmap_(nullptr),
+ non_moving_space_inter_region_bitmap_(nullptr),
reclaimed_bytes_ratio_sum_(0.f),
young_gen_(young_gen),
skipped_blocks_lock_("concurrent copying bytes blocks lock", kMarkSweepMarkStackLock),
@@ -286,12 +287,32 @@
gc_barrier_->Increment(self, barrier_count);
}
+void ConcurrentCopying::CreateInterRegionRefBitmaps() {
+ DCHECK(kEnableGenerationalConcurrentCopyingCollection);
+ DCHECK(region_space_inter_region_bitmap_ == nullptr);
+ DCHECK(non_moving_space_inter_region_bitmap_ == nullptr);
+ DCHECK(region_space_ != nullptr);
+ DCHECK(heap_->non_moving_space_ != nullptr);
+ // Region-space
+ region_space_inter_region_bitmap_.reset(accounting::ContinuousSpaceBitmap::Create(
+ "region-space inter region ref bitmap",
+ reinterpret_cast<uint8_t*>(region_space_->Begin()),
+ region_space_->Limit() - region_space_->Begin()));
+ CHECK(region_space_inter_region_bitmap_ != nullptr)
+ << "Couldn't allocate region-space inter region ref bitmap";
+
+ // non-moving-space
+ non_moving_space_inter_region_bitmap_.reset(accounting::ContinuousSpaceBitmap::Create(
+ "non-moving-space inter region ref bitmap",
+ reinterpret_cast<uint8_t*>(heap_->non_moving_space_->Begin()),
+ heap_->non_moving_space_->Limit() - heap_->non_moving_space_->Begin()));
+ CHECK(non_moving_space_inter_region_bitmap_ != nullptr)
+ << "Couldn't allocate non-moving-space inter region ref bitmap";
+}
+
void ConcurrentCopying::BindBitmaps() {
Thread* self = Thread::Current();
WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
- uintptr_t continuous_spaces_begin = UINTPTR_MAX;
- uintptr_t continuous_spaces_limit = 0;
- DCHECK(inter_region_bitmap_ == nullptr);
// Mark all of the spaces we never collect as immune.
for (const auto& space : heap_->GetContinuousSpaces()) {
if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyNeverCollect ||
@@ -301,6 +322,7 @@
} else {
CHECK(!space->IsZygoteSpace());
CHECK(!space->IsImageSpace());
+ CHECK(space == region_space_ || space == heap_->non_moving_space_);
if (kEnableGenerationalConcurrentCopyingCollection) {
if (space == region_space_) {
region_space_bitmap_ = region_space_->GetMarkBitmap();
@@ -323,11 +345,6 @@
// be captured after the thread-flip of this GC cycle, as that is when
// the young-gen for the next GC cycle starts getting populated.
heap_->GetCardTable()->ClearCardRange(space->Begin(), space->Limit());
-
- continuous_spaces_begin =
- std::min(continuous_spaces_begin, reinterpret_cast<uintptr_t>(space->Begin()));
- continuous_spaces_limit =
- std::max(continuous_spaces_limit, reinterpret_cast<uintptr_t>(space->Limit()));
}
} else {
if (space == region_space_) {
@@ -339,18 +356,10 @@
}
}
}
- if (kEnableGenerationalConcurrentCopyingCollection) {
- if (young_gen_) {
- for (const auto& space : GetHeap()->GetDiscontinuousSpaces()) {
- CHECK(space->IsLargeObjectSpace());
- space->AsLargeObjectSpace()->CopyLiveToMarked();
- }
- } else {
- inter_region_bitmap_.reset(accounting::ContinuousSpaceBitmap::Create(
- "inter region ref bitmap",
- reinterpret_cast<uint8_t*>(continuous_spaces_begin),
- continuous_spaces_limit - continuous_spaces_begin));
- CHECK(inter_region_bitmap_ != nullptr) << "Couldn't allocate inter region ref bitmap";
+ if (kEnableGenerationalConcurrentCopyingCollection && young_gen_) {
+ for (const auto& space : GetHeap()->GetDiscontinuousSpaces()) {
+ CHECK(space->IsLargeObjectSpace());
+ space->AsLargeObjectSpace()->CopyLiveToMarked();
}
}
}
@@ -1112,12 +1121,22 @@
}
ComputeLiveBytesAndMarkRefFieldsVisitor</*kHandleInterRegionRefs*/ true>
visitor(this, obj_region_idx);
- ref->VisitReferences</*kVisitNativeRoots=*/true, kDefaultVerifyFlags, kWithoutReadBarrier>(
+ ref->VisitReferences</*kVisitNativeRoots=*/ true, kDefaultVerifyFlags, kWithoutReadBarrier>(
visitor, visitor);
// Mark the corresponding card dirty if the object contains any
// inter-region reference.
if (visitor.ContainsInterRegionRefs()) {
- inter_region_bitmap_->Set(ref);
+ if (obj_region_idx == static_cast<size_t>(-1)) {
+ // If an inter-region ref has been found in a non-region-space, then it
+ // must be non-moving-space. This is because this function cannot be
+ // called on a immune-space object, and a large-object-space object has
+ // only class object reference, which is either in some immune-space, or
+ // in non-moving-space.
+ DCHECK(heap_->non_moving_space_->HasAddress(ref));
+ non_moving_space_inter_region_bitmap_->Set(ref);
+ } else {
+ region_space_inter_region_bitmap_->Set(ref);
+ }
}
}
@@ -1427,11 +1446,15 @@
}
}
ScanDirtyObject</*kNoUnEvac*/ true>(obj);
- } else if (space != region_space_ || region_space_->IsInUnevacFromSpace(obj)) {
+ } else if (space != region_space_) {
+ DCHECK(space == heap_->non_moving_space_);
// We need to process un-evac references as they may be unprocessed,
// if they skipped the marking phase due to heap mutation.
ScanDirtyObject</*kNoUnEvac*/ false>(obj);
- inter_region_bitmap_->Clear(obj);
+ non_moving_space_inter_region_bitmap_->Clear(obj);
+ } else if (region_space_->IsInUnevacFromSpace(obj)) {
+ ScanDirtyObject</*kNoUnEvac*/ false>(obj);
+ region_space_inter_region_bitmap_->Clear(obj);
}
},
accounting::CardTable::kCardAged);
@@ -1443,16 +1466,20 @@
ScanDirtyObject</*kNoUnEvac*/ true>(obj);
};
if (space == region_space_) {
- region_space_->ScanUnevacFromSpace(inter_region_bitmap_.get(), visitor);
+ region_space_->ScanUnevacFromSpace(region_space_inter_region_bitmap_.get(), visitor);
} else {
- inter_region_bitmap_->VisitMarkedRange(reinterpret_cast<uintptr_t>(space->Begin()),
- reinterpret_cast<uintptr_t>(space->End()),
- visitor);
+ DCHECK(space == heap_->non_moving_space_);
+ non_moving_space_inter_region_bitmap_->VisitMarkedRange(
+ reinterpret_cast<uintptr_t>(space->Begin()),
+ reinterpret_cast<uintptr_t>(space->End()),
+ visitor);
}
}
}
// Done scanning unevac space.
done_scanning_.store(true, std::memory_order_release);
+ // NOTE: inter-region-ref bitmaps can be cleared here to release memory, if needed.
+ // Currently we do it in ReclaimPhase().
if (kVerboseMode) {
LOG(INFO) << "GC end of ScanCardsForSpace";
}
@@ -3527,7 +3554,8 @@
// We do not currently use the region space cards at all, madvise them away to save ram.
heap_->GetCardTable()->ClearCardRange(region_space_->Begin(), region_space_->Limit());
} else if (kEnableGenerationalConcurrentCopyingCollection && !young_gen_) {
- inter_region_bitmap_.reset();
+ region_space_inter_region_bitmap_->Clear();
+ non_moving_space_inter_region_bitmap_->Clear();
}
{
MutexLock mu(self, skipped_blocks_lock_);
diff --git a/runtime/gc/collector/concurrent_copying.h b/runtime/gc/collector/concurrent_copying.h
index aabfc8e..a2d4837 100644
--- a/runtime/gc/collector/concurrent_copying.h
+++ b/runtime/gc/collector/concurrent_copying.h
@@ -98,6 +98,9 @@
return kCollectorTypeCC;
}
void RevokeAllThreadLocalBuffers() override;
+ // Creates inter-region ref bitmaps for region-space and non-moving-space.
+ // Gets called in Heap construction after the two spaces are created.
+ void CreateInterRegionRefBitmaps();
void SetRegionSpace(space::RegionSpace* region_space) {
DCHECK(region_space != nullptr);
region_space_ = region_space;
@@ -391,7 +394,8 @@
size_t gc_count_;
// Bit is set if the corresponding object has inter-region references that
// were found during the marking phase of two-phase full-heap GC cycle.
- std::unique_ptr<accounting::ContinuousSpaceBitmap> inter_region_bitmap_;
+ std::unique_ptr<accounting::ContinuousSpaceBitmap> region_space_inter_region_bitmap_;
+ std::unique_ptr<accounting::ContinuousSpaceBitmap> non_moving_space_inter_region_bitmap_;
// reclaimed_bytes_ratio = reclaimed_bytes/num_allocated_bytes per GC cycle
float reclaimed_bytes_ratio_sum_;
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index d868aba..bf8aaae 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -666,6 +666,9 @@
concurrent_copying_collector_->SetRegionSpace(region_space_);
if (kEnableGenerationalConcurrentCopyingCollection) {
young_concurrent_copying_collector_->SetRegionSpace(region_space_);
+ // At this point, non-moving space should be created.
+ DCHECK(non_moving_space_ != nullptr);
+ concurrent_copying_collector_->CreateInterRegionRefBitmaps();
}
garbage_collectors_.push_back(concurrent_copying_collector_);
if (kEnableGenerationalConcurrentCopyingCollection) {
@@ -2736,7 +2739,7 @@
// active_concurrent_copying_collector_. So we should not concurrency here.
active_concurrent_copying_collector_ = (gc_type == collector::kGcTypeSticky) ?
young_concurrent_copying_collector_ : concurrent_copying_collector_;
- active_concurrent_copying_collector_->SetRegionSpace(region_space_);
+ DCHECK(active_concurrent_copying_collector_->RegionSpace() == region_space_);
}
collector = active_concurrent_copying_collector_;
break;
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index b7ac1e8..9ce4749 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -240,11 +240,6 @@
runtime->PreZygoteFork();
- if (Trace::GetMethodTracingMode() != TracingMode::kTracingInactive) {
- // Tracing active, pause it.
- Trace::Pause();
- }
-
// Grab thread before fork potentially makes Thread::pthread_key_self_ unusable.
return reinterpret_cast<jlong>(ThreadForEnv(env));
}
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 8bec2d9..f459f9c 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -160,6 +160,7 @@
}
void Thread::InitTlsEntryPoints() {
+ ScopedTrace trace("InitTlsEntryPoints");
// Insert a placeholder so we can easily tell if we call an unimplemented entry point.
uintptr_t* begin = reinterpret_cast<uintptr_t*>(&tlsPtr_.jni_entrypoints);
uintptr_t* end = reinterpret_cast<uintptr_t*>(
@@ -903,6 +904,8 @@
tlsPtr_.pthread_self = pthread_self();
CHECK(is_started_);
+ ScopedTrace trace("Thread::Init");
+
SetUpAlternateSignalStack();
if (!InitStackHwm()) {
return false;
@@ -912,7 +915,10 @@
RemoveSuspendTrigger();
InitCardTable();
InitTid();
- interpreter::InitInterpreterTls(this);
+ {
+ ScopedTrace trace2("InitInterpreterTls");
+ interpreter::InitInterpreterTls(this);
+ }
#ifdef ART_TARGET_ANDROID
__get_tls()[TLS_SLOT_ART_THREAD_SELF] = this;
@@ -936,6 +942,7 @@
}
}
+ ScopedTrace trace3("ThreadList::Register");
thread_list->Register(this);
return true;
}
@@ -943,6 +950,7 @@
template <typename PeerAction>
Thread* Thread::Attach(const char* thread_name, bool as_daemon, PeerAction peer_action) {
Runtime* runtime = Runtime::Current();
+ ScopedTrace trace("Thread::Attach");
if (runtime == nullptr) {
LOG(ERROR) << "Thread attaching to non-existent runtime: " <<
((thread_name != nullptr) ? thread_name : "(Unnamed)");
@@ -950,6 +958,7 @@
}
Thread* self;
{
+ ScopedTrace trace2("Thread birth");
MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);
if (runtime->IsShuttingDownLocked()) {
LOG(WARNING) << "Thread attaching while runtime is shutting down: " <<
@@ -1251,6 +1260,7 @@
}
bool Thread::InitStackHwm() {
+ ScopedTrace trace("InitStackHwm");
void* read_stack_base;
size_t read_stack_size;
size_t read_guard_size;
diff --git a/runtime/trace.cc b/runtime/trace.cc
index f6c36cf..ce955d8 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -517,106 +517,6 @@
}
}
-void Trace::Pause() {
- bool stop_alloc_counting = false;
- Runtime* runtime = Runtime::Current();
- Trace* the_trace = nullptr;
-
- Thread* const self = Thread::Current();
- pthread_t sampling_pthread = 0U;
- {
- MutexLock mu(self, *Locks::trace_lock_);
- if (the_trace_ == nullptr) {
- LOG(ERROR) << "Trace pause requested, but no trace currently running";
- return;
- } else {
- the_trace = the_trace_;
- sampling_pthread = sampling_pthread_;
- }
- }
-
- if (sampling_pthread != 0U) {
- {
- MutexLock mu(self, *Locks::trace_lock_);
- the_trace_ = nullptr;
- }
- CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, nullptr), "sampling thread shutdown");
- sampling_pthread_ = 0U;
- {
- MutexLock mu(self, *Locks::trace_lock_);
- the_trace_ = the_trace;
- }
- }
-
- if (the_trace != nullptr) {
- gc::ScopedGCCriticalSection gcs(self,
- gc::kGcCauseInstrumentation,
- gc::kCollectorTypeInstrumentation);
- ScopedSuspendAll ssa(__FUNCTION__);
- stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0;
-
- if (the_trace->trace_mode_ == TraceMode::kSampling) {
- MutexLock mu(self, *Locks::thread_list_lock_);
- runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr);
- } else {
- runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey);
- runtime->GetInstrumentation()->RemoveListener(
- the_trace,
- instrumentation::Instrumentation::kMethodEntered |
- instrumentation::Instrumentation::kMethodExited |
- instrumentation::Instrumentation::kMethodUnwind);
- }
- }
-
- if (stop_alloc_counting) {
- // Can be racy since SetStatsEnabled is not guarded by any locks.
- Runtime::Current()->SetStatsEnabled(false);
- }
-}
-
-void Trace::Resume() {
- Thread* self = Thread::Current();
- Trace* the_trace;
- {
- MutexLock mu(self, *Locks::trace_lock_);
- if (the_trace_ == nullptr) {
- LOG(ERROR) << "No trace to resume (or sampling mode), ignoring this request";
- return;
- }
- the_trace = the_trace_;
- }
-
- Runtime* runtime = Runtime::Current();
-
- // Enable count of allocs if specified in the flags.
- bool enable_stats = (the_trace->flags_ & kTraceCountAllocs) != 0;
-
- {
- gc::ScopedGCCriticalSection gcs(self,
- gc::kGcCauseInstrumentation,
- gc::kCollectorTypeInstrumentation);
- ScopedSuspendAll ssa(__FUNCTION__);
-
- // Reenable.
- if (the_trace->trace_mode_ == TraceMode::kSampling) {
- CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread,
- reinterpret_cast<void*>(the_trace->interval_us_)), "Sampling profiler thread");
- } else {
- runtime->GetInstrumentation()->AddListener(the_trace,
- instrumentation::Instrumentation::kMethodEntered |
- instrumentation::Instrumentation::kMethodExited |
- instrumentation::Instrumentation::kMethodUnwind);
- // TODO: In full-PIC mode, we don't need to fully deopt.
- runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey);
- }
- }
-
- // Can't call this when holding the mutator lock.
- if (enable_stats) {
- runtime->SetStatsEnabled(true);
- }
-}
-
TracingMode Trace::GetMethodTracingMode() {
MutexLock mu(Thread::Current(), *Locks::trace_lock_);
if (the_trace_ == nullptr) {
diff --git a/runtime/trace.h b/runtime/trace.h
index 1089962..582f756 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -156,9 +156,6 @@
REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_,
!Locks::trace_lock_);
- static void Pause() REQUIRES(!Locks::trace_lock_, !Locks::thread_list_lock_);
- static void Resume() REQUIRES(!Locks::trace_lock_);
-
// Stop tracing. This will finish the trace and write it to file/send it via DDMS.
static void Stop()
REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::trace_lock_);
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index c66f71d..3c65b01 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -198,5 +198,30 @@
modes: [device],
bug: 116446372,
names: ["libcore.libcore.io.FdsanTest#testSocket"]
+},
+{
+ description: "Host implementation of android_getaddrinfo differs from device implementation",
+ result: EXEC_FAILED,
+ modes: [host],
+ bug: 121230364,
+ names: [
+ "libcore.libcore.net.InetAddressUtilsTest#parseNumericAddress[8]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_isNotNumericAddress[10]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_isNotNumericAddress[11]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_isNotNumericAddress[12]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_isNotNumericAddress[5]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_isNotNumericAddress[6]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_isNotNumericAddress[7]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_isNotNumericAddress[8]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_isNotNumericAddress[9]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[10]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[11]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[12]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[5]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[6]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[7]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[8]",
+ "libcore.libcore.net.InetAddressUtilsTest#test_parseNonNumericAddress[9]"
+ ]
}
]