aboutsummaryrefslogtreecommitdiff
path: root/src/gfxstream/guest/android-emu/aemu/base/AndroidSubAllocator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gfxstream/guest/android-emu/aemu/base/AndroidSubAllocator.cpp')
-rw-r--r--src/gfxstream/guest/android-emu/aemu/base/AndroidSubAllocator.cpp238
1 files changed, 238 insertions, 0 deletions
diff --git a/src/gfxstream/guest/android-emu/aemu/base/AndroidSubAllocator.cpp b/src/gfxstream/guest/android-emu/aemu/base/AndroidSubAllocator.cpp
new file mode 100644
index 00000000000..5f5d387266f
--- /dev/null
+++ b/src/gfxstream/guest/android-emu/aemu/base/AndroidSubAllocator.cpp
@@ -0,0 +1,238 @@
+// 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 "aemu/base/AndroidSubAllocator.h"
+
+#include "aemu/base/address_space.h"
+#include "aemu/base/files/Stream.h"
+
+#include <iomanip>
+#include <sstream>
+#include <string>
+
+#include <log/log.h>
+
+namespace gfxstream {
+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 gfxstream