Sync guest SubAllocator with host version
+ make it a different class to avoid odr violation
Change-Id: I81079ee5aee9e5066acd9f797c49c094dc5df196
diff --git a/Android.bp b/Android.bp
index 2f333a0..00fabf3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4,7 +4,7 @@
srcs: [
"android-emu/android/base/AlignedBuf.cpp",
"android-emu/android/base/Pool.cpp",
- "android-emu/android/base/SubAllocator.cpp",
+ "android-emu/android/base/AndroidSubAllocator.cpp",
"android-emu/android/base/files/MemStream.cpp",
"android-emu/android/base/files/Stream.cpp",
"android-emu/android/base/files/StreamSerializing.cpp",
diff --git a/BUILD.gn b/BUILD.gn
index c6e0201..b02c012 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -5,8 +5,8 @@
"android-emu/android/base/Pool.cpp",
"android-emu/android/base/Pool.h",
"android-emu/android/base/ring_buffer.c",
- "android-emu/android/base/SubAllocator.cpp",
- "android-emu/android/base/SubAllocator.h",
+ "android-emu/android/base/AndroidSubAllocator.cpp",
+ "android-emu/android/base/AndroidSubAllocator.h",
"android-emu/android/base/files/MemStream.cpp",
"android-emu/android/base/files/MemStream.h",
"android-emu/android/base/files/Stream.cpp",
diff --git a/android-emu/Android.mk b/android-emu/Android.mk
index 6de495e..4be199b 100644
--- a/android-emu/Android.mk
+++ b/android-emu/Android.mk
@@ -18,7 +18,7 @@
android/base/Pool.cpp \
android/base/ring_buffer.c \
android/base/StringFormat.cpp \
- android/base/SubAllocator.cpp \
+ android/base/AndroidSubAllocator.cpp \
android/base/synchronization/AndroidMessageChannel.cpp \
android/base/threads/AndroidFunctorThread.cpp \
android/base/threads/AndroidThreadStore.cpp \
diff --git a/android-emu/CMakeLists.txt b/android-emu/CMakeLists.txt
index e6482d8..5b4b280 100644
--- a/android-emu/CMakeLists.txt
+++ b/android-emu/CMakeLists.txt
@@ -1,8 +1,8 @@
# This is an autogenerated file! Do not edit!
# instead run make from .../device/generic/goldfish-opengl
# which will re-generate this file.
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/android-emu/Android.mk" "3654f06acfa661c75b91fe271337a63a77326a69b4247026996c40bff8138bde")
-set(androidemu_src android/base/AlignedBuf.cpp android/base/files/MemStream.cpp android/base/files/Stream.cpp android/base/files/StreamSerializing.cpp android/base/Pool.cpp android/base/ring_buffer.c android/base/StringFormat.cpp android/base/SubAllocator.cpp android/base/synchronization/AndroidMessageChannel.cpp android/base/threads/AndroidFunctorThread.cpp android/base/threads/AndroidThreadStore.cpp android/base/threads/AndroidThread_pthread.cpp android/base/threads/AndroidWorkPool.cpp android/base/Tracing.cpp android/utils/debug.c)
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/android-emu/Android.mk" "e7c9acc2277e7c651d6e722f96705a1fd445441b5ab6bb5b6d5b4c46dddfc702")
+set(androidemu_src android/base/AlignedBuf.cpp android/base/files/MemStream.cpp android/base/files/Stream.cpp android/base/files/StreamSerializing.cpp android/base/Pool.cpp android/base/ring_buffer.c android/base/StringFormat.cpp android/base/AndroidSubAllocator.cpp android/base/synchronization/AndroidMessageChannel.cpp android/base/threads/AndroidFunctorThread.cpp android/base/threads/AndroidThreadStore.cpp android/base/threads/AndroidThread_pthread.cpp android/base/threads/AndroidWorkPool.cpp android/base/Tracing.cpp android/utils/debug.c)
android_add_shared_library(androidemu)
target_include_directories(androidemu PRIVATE ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
target_compile_definitions(androidemu PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"androidemu\"")
diff --git a/android-emu/android/base/AndroidSubAllocator.cpp b/android-emu/android/base/AndroidSubAllocator.cpp
new file mode 100644
index 0000000..0b17a8a
--- /dev/null
+++ b/android-emu/android/base/AndroidSubAllocator.cpp
@@ -0,0 +1,240 @@
+// Copyright 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.
+#include "android/base/AndroidSubAllocator.h"
+
+#include "android/base/address_space.h"
+#include "android/base/files/Stream.h"
+
+#include <iomanip>
+#include <sstream>
+#include <string>
+
+#include <log/log.h>
+
+namespace android {
+namespace base {
+namespace guest {
+
+class SubAllocator::Impl {
+public:
+ Impl(
+ void* _buffer,
+ uint64_t _totalSize,
+ uint64_t _pageSize) :
+ buffer(_buffer),
+ totalSize(_totalSize),
+ pageSize(_pageSize),
+ startAddr((uintptr_t)buffer),
+ endAddr(startAddr + totalSize) {
+
+ address_space_allocator_init(
+ &addr_alloc,
+ totalSize,
+ 32);
+ }
+
+ ~Impl() {
+ address_space_allocator_destroy_nocleanup(&addr_alloc);
+ }
+
+ void clear() {
+ address_space_allocator_destroy_nocleanup(&addr_alloc);
+ address_space_allocator_init(
+ &addr_alloc,
+ totalSize,
+ 32);
+ }
+
+ bool save(Stream* stream) {
+ address_space_allocator_iter_func_t allocatorSaver =
+ [](void* context, struct address_space_allocator* allocator) {
+ Stream* stream = reinterpret_cast<Stream*>(context);
+ stream->putBe32(allocator->size);
+ stream->putBe32(allocator->capacity);
+ stream->putBe64(allocator->total_bytes);
+ };
+ address_block_iter_func_t allocatorBlockSaver =
+ [](void* context, struct address_block* block) {
+ Stream* stream = reinterpret_cast<Stream*>(context);
+ stream->putBe64(block->offset);
+ stream->putBe64(block->size_available);
+ };
+ address_space_allocator_run(
+ &addr_alloc,
+ (void*)stream,
+ allocatorSaver,
+ allocatorBlockSaver);
+
+ stream->putBe64(pageSize);
+ stream->putBe64(totalSize);
+ stream->putBe32(allocCount);
+
+ return true;
+ }
+
+ bool load(Stream* stream) {
+ clear();
+ address_space_allocator_iter_func_t allocatorLoader =
+ [](void* context, struct address_space_allocator* allocator) {
+ Stream* stream = reinterpret_cast<Stream*>(context);
+ allocator->size = stream->getBe32();
+ allocator->capacity = stream->getBe32();
+ allocator->total_bytes = stream->getBe64();
+ };
+ address_block_iter_func_t allocatorBlockLoader =
+ [](void* context, struct address_block* block) {
+ Stream* stream = reinterpret_cast<Stream*>(context);
+ block->offset = stream->getBe64();
+ block->size_available = stream->getBe64();
+ };
+ address_space_allocator_run(
+ &addr_alloc,
+ (void*)stream,
+ allocatorLoader,
+ allocatorBlockLoader);
+
+ pageSize = stream->getBe64();
+ totalSize = stream->getBe64();
+ allocCount = stream->getBe32();
+
+ return true;
+ }
+
+ bool postLoad(void* postLoadBuffer) {
+ buffer = postLoadBuffer;
+ startAddr =
+ (uint64_t)(uintptr_t)postLoadBuffer;
+ return true;
+ }
+
+ void rangeCheck(const char* task, void* ptr) {
+ uint64_t addr = (uintptr_t)ptr;
+ if (addr < startAddr ||
+ addr > endAddr) {
+ std::stringstream ss;
+ ss << "SubAllocator " << task << ": ";
+ ss << "Out of range: " << std::hex << addr << " ";
+ ss << "Range: " <<
+ std::hex << startAddr << " " <<
+ std::hex << endAddr;
+ std::string msg = ss.str();
+ ALOGE("Fatal: %s\n", msg.c_str());
+ }
+ }
+
+ uint64_t getOffset(void* checkedPtr) {
+ uint64_t addr = (uintptr_t)checkedPtr;
+ return addr - startAddr;
+ }
+
+ bool free(void* ptr) {
+ if (!ptr) return false;
+
+ rangeCheck("free", ptr);
+ if (EINVAL == address_space_allocator_deallocate(
+ &addr_alloc, getOffset(ptr))) {
+ return false;
+ }
+
+ --allocCount;
+ return true;
+ }
+
+ void freeAll() {
+ address_space_allocator_reset(&addr_alloc);
+ allocCount = 0;
+ }
+
+ void* alloc(size_t wantedSize) {
+ if (wantedSize == 0) return nullptr;
+
+ uint64_t wantedSize64 =
+ (uint64_t)wantedSize;
+
+ size_t toPageSize =
+ pageSize *
+ ((wantedSize + pageSize - 1) / pageSize);
+
+ uint64_t offset =
+ address_space_allocator_allocate(
+ &addr_alloc, toPageSize);
+
+ if (offset == ANDROID_EMU_ADDRESS_SPACE_BAD_OFFSET) {
+ return nullptr;
+ }
+
+ ++allocCount;
+ return (void*)(uintptr_t)(startAddr + offset);
+ }
+
+ bool empty() const {
+ return allocCount == 0;
+ }
+
+ void* buffer;
+ uint64_t totalSize;
+ uint64_t pageSize;
+ uint64_t startAddr;
+ uint64_t endAddr;
+ struct address_space_allocator addr_alloc;
+ uint32_t allocCount = 0;
+};
+
+SubAllocator::SubAllocator(
+ void* buffer,
+ uint64_t totalSize,
+ uint64_t pageSize) :
+ mImpl(
+ new SubAllocator::Impl(buffer, totalSize, pageSize)) { }
+
+SubAllocator::~SubAllocator() {
+ delete mImpl;
+}
+
+// Snapshotting
+bool SubAllocator::save(Stream* stream) {
+ return mImpl->save(stream);
+}
+
+bool SubAllocator::load(Stream* stream) {
+ return mImpl->load(stream);
+}
+
+bool SubAllocator::postLoad(void* postLoadBuffer) {
+ return mImpl->postLoad(postLoadBuffer);
+}
+
+void* SubAllocator::alloc(size_t wantedSize) {
+ return mImpl->alloc(wantedSize);
+}
+
+bool SubAllocator::free(void* ptr) {
+ return mImpl->free(ptr);
+}
+
+void SubAllocator::freeAll() {
+ mImpl->freeAll();
+}
+
+uint64_t SubAllocator::getOffset(void* ptr) {
+ return mImpl->getOffset(ptr);
+}
+
+bool SubAllocator::empty() const {
+ return mImpl->empty();
+}
+
+} // namespace guest
+} // namespace base
+} // namespace android
diff --git a/android-emu/android/base/SubAllocator.h b/android-emu/android/base/AndroidSubAllocator.h
similarity index 86%
rename from android-emu/android/base/SubAllocator.h
rename to android-emu/android/base/AndroidSubAllocator.h
index b2363bd..8442137 100644
--- a/android-emu/android/base/SubAllocator.h
+++ b/android-emu/android/base/AndroidSubAllocator.h
@@ -20,6 +20,16 @@
namespace android {
namespace base {
+class Stream;
+
+} // namespace base
+} // namespace android
+
+namespace android {
+namespace base {
+namespace guest {
+
+
// Class to create sub-allocations in an existing buffer. Similar interface to
// Pool, but underlying mechanism is different as it's difficult to combine
// same-size heaps in Pool with a preallocated buffer.
@@ -36,12 +46,20 @@
// SubAllocator, but the prealloced buffer is not freed.
~SubAllocator();
+ // Snapshotting
+ bool save(Stream* stream);
+ bool load(Stream* stream);
+ bool postLoad(void* postLoadBuffer);
+
// returns null if the allocation cannot be satisfied.
void* alloc(size_t wantedSize);
- void free(void* ptr);
+ // returns true if |ptr| came from alloc(), false otherwise
+ bool free(void* ptr);
void freeAll();
uint64_t getOffset(void* ptr);
+ bool empty() const;
+
// Convenience function to allocate an array
// of objects of type T.
template <class T>
@@ -80,5 +98,6 @@
Impl* mImpl = nullptr;
};
+} // namespace guest
} // namespace base
} // namespace android
diff --git a/android-emu/android/base/SubAllocator.cpp b/android-emu/android/base/SubAllocator.cpp
deleted file mode 100644
index 99d7b78..0000000
--- a/android-emu/android/base/SubAllocator.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 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.
-#include "android/base/SubAllocator.h"
-
-#include "android/base/address_space.h"
-
-#include <log/log.h>
-
-#include <iomanip>
-#include <sstream>
-#include <string>
-
-namespace android {
-namespace base {
-
-class SubAllocator::Impl {
-public:
- Impl(
- void* _buffer,
- uint64_t _totalSize,
- uint64_t _pageSize) :
- buffer(_buffer),
- totalSize(_totalSize),
- pageSize(_pageSize),
- startAddr((uintptr_t)buffer),
- endAddr(startAddr + totalSize) {
-
- address_space_allocator_init(
- &addr_alloc,
- totalSize,
- 32);
- }
-
- ~Impl() {
- address_space_allocator_destroy(&addr_alloc);
- }
-
- void rangeCheck(const char* task, void* ptr) {
- uint64_t addr = (uintptr_t)ptr;
- if (addr < startAddr ||
- addr > endAddr) {
- std::stringstream ss;
- ss << "SubAllocator " << task << ": ";
- ss << "Out of range: " << std::hex << addr << " ";
- ss << "Range: " <<
- std::hex << startAddr << " " <<
- std::hex << endAddr;
- std::string msg = ss.str();
- ALOGE("%s", msg.c_str());
- abort();
- }
- }
-
- uint64_t getOffset(void* checkedPtr) {
- uint64_t addr = (uintptr_t)checkedPtr;
- return addr - startAddr;
- }
-
- void free(void* ptr) {
- if (!ptr) return;
-
- rangeCheck("free", ptr);
- address_space_allocator_deallocate(
- &addr_alloc, getOffset(ptr));
- }
-
- void freeAll() {
- address_space_allocator_reset(&addr_alloc);
- }
-
- void* alloc(size_t wantedSize) {
- if (wantedSize == 0) return nullptr;
-
- size_t toPageSize =
- pageSize *
- ((wantedSize + pageSize - 1) / pageSize);
-
- uint64_t offset =
- address_space_allocator_allocate(
- &addr_alloc, toPageSize);
-
- if (offset == ANDROID_EMU_ADDRESS_SPACE_BAD_OFFSET) {
- return nullptr;
- }
-
- return (void*)(uintptr_t)(startAddr + offset);
- }
-
- void* buffer;
- uint64_t totalSize;
- uint64_t pageSize;
- uint64_t startAddr;
- uint64_t endAddr;
- struct address_space_allocator addr_alloc;
-};
-
-SubAllocator::SubAllocator(
- void* buffer,
- uint64_t totalSize,
- uint64_t pageSize) :
- mImpl(
- new SubAllocator::Impl(buffer, totalSize, pageSize)) { }
-
-SubAllocator::~SubAllocator() {
- delete mImpl;
-}
-
-void* SubAllocator::alloc(size_t wantedSize) {
- return mImpl->alloc(wantedSize);
-}
-
-void SubAllocator::free(void* ptr) {
- mImpl->free(ptr);
-}
-
-void SubAllocator::freeAll() {
- mImpl->freeAll();
-}
-
-uint64_t SubAllocator::getOffset(void* ptr) {
- return mImpl->getOffset(ptr);
-}
-
-} // namespace base
-} // namespace android
diff --git a/android-emu/android/base/address_space.h b/android-emu/android/base/address_space.h
index 50c9bbd..e7b43fd 100644
--- a/android-emu/android/base/address_space.h
+++ b/android-emu/android/base/address_space.h
@@ -18,10 +18,15 @@
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
ANDROID_BEGIN_HEADER
+#ifdef ADDRESS_SPACE_NAMESPACE
+namespace ADDRESS_SPACE_NAMESPACE {
+#endif
+
// This is ported from goldfish_address_space, allowing it to be used for
// general sub-allocations of any buffer range.
// It is also a pure header library, so there are no compiler tricks needed
@@ -33,8 +38,13 @@
*/
struct address_block {
uint64_t offset;
- uint64_t size : 63;
- uint64_t available : 1;
+ union {
+ uint64_t size_available; /* VMSTATE_x does not support bit fields */
+ struct {
+ uint64_t size : 63;
+ uint64_t available : 1;
+ };
+ };
};
/* A dynamic array of address blocks, with the following invariant:
@@ -53,7 +63,6 @@
/* The assert function to abort if something goes wrong. */
static void address_space_assert(bool condition) {
- (void)condition;
#ifdef ANDROID_EMU_ADDRESS_SPACE_ASSERT_FUNC
ANDROID_EMU_ADDRESS_SPACE_ASSERT_FUNC(condition);
#else
@@ -61,7 +70,7 @@
#endif
}
-void* address_space_malloc0(size_t size) {
+static void* address_space_malloc0(size_t size) {
#ifdef ANDROID_EMU_ADDRESS_SPACE_MALLOC0_FUNC
return ANDROID_EMU_ADDRESS_SPACE_MALLOC0_FUNC(size);
#else
@@ -71,7 +80,7 @@
#endif
}
-void* address_space_realloc(void* ptr, size_t size) {
+static void* address_space_realloc(void* ptr, size_t size) {
#ifdef ANDROID_EMU_ADDRESS_SPACE_REALLOC_FUNC
return ANDROID_EMU_ADDRESS_SPACE_REALLOC_FUNC(ptr, size);
#else
@@ -80,7 +89,7 @@
#endif
}
-void address_space_free(void* ptr) {
+static void address_space_free(void* ptr) {
#ifdef ANDROID_EMU_ADDRESS_SPACE_FREE_FUNC
return ANDROID_EMU_ADDRESS_SPACE_FREE_FUNC(ptr);
#else
@@ -302,7 +311,8 @@
allocator->blocks =
(struct address_block*)
- address_space_malloc0(sizeof(struct address_block) * initial_capacity);
+ malloc(sizeof(struct address_block) * initial_capacity);
+ memset(allocator->blocks, 0, sizeof(struct address_block) * initial_capacity);
address_space_assert(allocator->blocks);
struct address_block *block = allocator->blocks;
@@ -328,6 +338,15 @@
address_space_free(allocator->blocks);
}
+/* Destroy function if we don't care what was previoulsy allocated.
+ * have been merged into one block.
+ */
+static void address_space_allocator_destroy_nocleanup(
+ struct address_space_allocator *allocator)
+{
+ address_space_free(allocator->blocks);
+}
+
/* Resets the state of the allocator to the initial state without
* performing any dynamic memory management. */
static void address_space_allocator_reset(
@@ -343,4 +362,33 @@
block->available = 1;
}
+typedef void (*address_block_iter_func_t)(void* context, struct address_block*);
+typedef void (*address_space_allocator_iter_func_t)(void* context, struct address_space_allocator*);
+
+static void address_space_allocator_run(
+ struct address_space_allocator *allocator,
+ void* context,
+ address_space_allocator_iter_func_t allocator_func,
+ address_block_iter_func_t block_func)
+{
+ struct address_block *block = 0;
+ int size;
+ int i;
+
+ allocator_func(context, allocator);
+
+ block = allocator->blocks;
+ size = allocator->size;
+
+ address_space_assert(size >= 1);
+
+ for (i = 0; i < size; ++i, ++block) {
+ block_func(context, block);
+ }
+}
+
+#ifdef ADDRESS_SPACE_NAMESPACE
+}
+#endif
+
ANDROID_END_HEADER
diff --git a/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp b/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
index 2780d2a..b6bd91a 100644
--- a/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
+++ b/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
@@ -14,7 +14,7 @@
// limitations under the License.
#include "HostVisibleMemoryVirtualization.h"
-#include "android/base/SubAllocator.h"
+#include "android/base/AndroidSubAllocator.h"
#include "Resources.h"
#include "VkEncoder.h"
@@ -23,7 +23,7 @@
#include <set>
-using android::base::SubAllocator;
+using android::base::guest::SubAllocator;
namespace goldfish_vk {
@@ -296,7 +296,7 @@
memset(toFree, 0x0, sizeof(SubAlloc));
}
-bool canSubAlloc(android::base::SubAllocator* subAlloc, VkDeviceSize size) {
+bool canSubAlloc(android::base::guest::SubAllocator* subAlloc, VkDeviceSize size) {
auto ptr = subAlloc->alloc(size);
if (!ptr) return false;
subAlloc->free(ptr);
diff --git a/system/vulkan_enc/HostVisibleMemoryVirtualization.h b/system/vulkan_enc/HostVisibleMemoryVirtualization.h
index ad25353..84e39bb 100644
--- a/system/vulkan_enc/HostVisibleMemoryVirtualization.h
+++ b/system/vulkan_enc/HostVisibleMemoryVirtualization.h
@@ -20,9 +20,11 @@
namespace android {
namespace base {
+namespace guest {
class SubAllocator;
+} // namespace guest
} // namespace base
} // namespace android
@@ -81,7 +83,7 @@
VkDeviceSize allocSize = 0;
VkDeviceSize mappedSize = 0;
uint8_t* mappedPtr = nullptr;
- android::base::SubAllocator* subAlloc = nullptr;
+ android::base::guest::SubAllocator* subAlloc = nullptr;
};
VkResult finishHostMemAllocInit(
@@ -106,7 +108,7 @@
VkDeviceMemory baseMemory = VK_NULL_HANDLE;
VkDeviceSize baseOffset = 0;
- android::base::SubAllocator* subAlloc = nullptr;
+ android::base::guest::SubAllocator* subAlloc = nullptr;
VkDeviceMemory subMemory = VK_NULL_HANDLE;
};
@@ -117,5 +119,5 @@
void subFreeHostMemory(SubAlloc* toFree);
-bool canSubAlloc(android::base::SubAllocator* subAlloc, VkDeviceSize size);
+bool canSubAlloc(android::base::guest::SubAllocator* subAlloc, VkDeviceSize size);
} // namespace goldfish_vk