MemoryDealer.cpp revision 83c0446f27b9542d6c2e724817b2b2d8d1f55085
1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/* 2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * 4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License. 6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at 7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * 8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * 10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and 14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License. 15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */ 16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 17edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#define LOG_TAG "MemoryDealer" 18edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 19c5b2c0bf8007562536b822eb060fc54a01f8e08bMathias Agopian#include <binder/MemoryDealer.h> 20edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Log.h> 22c5b2c0bf8007562536b822eb060fc54a01f8e08bMathias Agopian#include <binder/IPCThreadState.h> 23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/SortedVector.h> 24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/String8.h> 25c5b2c0bf8007562536b822eb060fc54a01f8e08bMathias Agopian#include <binder/MemoryBase.h> 26edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 27edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdint.h> 28edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdio.h> 29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdlib.h> 30edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <fcntl.h> 31edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <unistd.h> 32edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <errno.h> 33edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <string.h> 34edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 35edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/stat.h> 36edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/types.h> 37edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/mman.h> 38edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/file.h> 39edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 40edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectnamespace android { 4183c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian// ---------------------------------------------------------------------------- 42edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 4383c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias AgopianHeapInterface::HeapInterface() { } 4483c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias AgopianHeapInterface::~HeapInterface() { } 4583c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian 4683c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian// ---------------------------------------------------------------------------- 4783c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian 4883c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias AgopianAllocatorInterface::AllocatorInterface() { } 4983c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias AgopianAllocatorInterface::~AllocatorInterface() { } 50edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 51edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 52edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 53edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectclass SimpleMemory : public MemoryBase { 54edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectpublic: 55edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project SimpleMemory(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size); 56edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project virtual ~SimpleMemory(); 57edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}; 58edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 59edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 60edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 61edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 62edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::Allocation::Allocation( 63edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const sp<MemoryDealer>& dealer, ssize_t offset, size_t size, 64edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const sp<IMemory>& memory) 65edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : mDealer(dealer), mOffset(offset), mSize(size), mMemory(memory) 66edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 67edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 68edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 69edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::Allocation::~Allocation() 70edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 71edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (mSize) { 72edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project /* NOTE: it's VERY important to not free allocations of size 0 because 73edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * they're special as they don't have any record in the allocator 74edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * and could alias some real allocation (their offset is zero). */ 75edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mDealer->deallocate(mOffset); 76edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 77edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 78edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 79edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsp<IMemoryHeap> MemoryDealer::Allocation::getMemory( 80edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project ssize_t* offset, size_t* size) const 81edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 82edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return mMemory->getMemory(offset, size); 83edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 84edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 85edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 86edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 87edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::MemoryDealer(size_t size, uint32_t flags, const char* name) 88edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : mHeap(new SharedHeap(size, flags, name)), 89edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mAllocator(new SimpleBestFitAllocator(size)) 90edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 91edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 92edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 93edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::MemoryDealer(const sp<HeapInterface>& heap) 94edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : mHeap(heap), 95edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mAllocator(new SimpleBestFitAllocator(heap->virtualSize())) 96edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 97edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 98edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 99edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::MemoryDealer( const sp<HeapInterface>& heap, 100edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const sp<AllocatorInterface>& allocator) 101edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : mHeap(heap), mAllocator(allocator) 102edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 103edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 104edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 105edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::~MemoryDealer() 106edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 107edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 108edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 109edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsp<IMemory> MemoryDealer::allocate(size_t size, uint32_t flags) 110edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 111edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project sp<IMemory> memory; 112edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const ssize_t offset = allocator()->allocate(size, flags); 113edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (offset >= 0) { 114edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project sp<IMemory> new_memory = heap()->mapMemory(offset, size); 115edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (new_memory != 0) { 116edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project memory = new Allocation(this, offset, size, new_memory); 117edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } else { 11883c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian LOGE("couldn't map [%8lx, %u]", offset, size); 119edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (size) { 120edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project /* NOTE: it's VERY important to not free allocations of size 0 121edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * because they're special as they don't have any record in the 122edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * allocator and could alias some real allocation 123edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * (their offset is zero). */ 124edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project allocator()->deallocate(offset); 125edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 126edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 127edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 128edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return memory; 129edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 130edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 131edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid MemoryDealer::deallocate(size_t offset) 132edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 133edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project allocator()->deallocate(offset); 134edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 135edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 136edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid MemoryDealer::dump(const char* what, uint32_t flags) const 137edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 138edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project allocator()->dump(what, flags); 139edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 140edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 141edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectconst sp<HeapInterface>& MemoryDealer::heap() const { 142edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return mHeap; 143edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 144edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 145edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectconst sp<AllocatorInterface>& MemoryDealer::allocator() const { 146edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return mAllocator; 147edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 148edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 149edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 150edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 151edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// align all the memory blocks on a cache-line boundary 152edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectconst int SimpleBestFitAllocator::kMemoryAlign = 32; 153edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 154edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) 155edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 156edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t pagesize = getpagesize(); 157edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); 158edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 159edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); 160edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mList.insertHead(node); 161edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 162edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 163edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleBestFitAllocator::~SimpleBestFitAllocator() 164edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 165edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project while(!mList.isEmpty()) { 166edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project delete mList.remove(mList.head()); 167edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 168edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 169edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 170edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsize_t SimpleBestFitAllocator::size() const 171edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 172edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return mHeapSize; 173edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 174edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 175edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) 176edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 177edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Mutex::Autolock _l(mLock); 178edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project ssize_t offset = alloc(size, flags); 179edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return offset; 180edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 181edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 182edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t SimpleBestFitAllocator::deallocate(size_t offset) 183edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 184edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Mutex::Autolock _l(mLock); 185edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t const * const freed = dealloc(offset); 186edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (freed) { 187edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return NO_ERROR; 188edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 189edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return NAME_NOT_FOUND; 190edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 191edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 192edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) 193edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 194edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (size == 0) { 195edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return 0; 196edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 197edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size = (size + kMemoryAlign-1) / kMemoryAlign; 198edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* free_chunk = 0; 199edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* cur = mList.head(); 200edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 201edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t pagesize = getpagesize(); 202edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project while (cur) { 203edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int extra = 0; 204edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (flags & PAGE_ALIGNED) 205edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; 206edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 207edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // best fit 208edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (cur->free && (cur->size >= (size+extra))) { 209edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if ((!free_chunk) || (cur->size < free_chunk->size)) { 210edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project free_chunk = cur; 211edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 212edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (cur->size == size) { 213edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project break; 214edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 215edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 216edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur = cur->next; 217edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 218edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 219edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (free_chunk) { 220edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const size_t free_size = free_chunk->size; 221edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project free_chunk->free = 0; 222edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project free_chunk->size = size; 223edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (free_size > size) { 224edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int extra = 0; 225edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (flags & PAGE_ALIGNED) 226edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; 227edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (extra) { 228edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* split = new chunk_t(free_chunk->start, extra); 229edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project free_chunk->start += extra; 230edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mList.insertBefore(free_chunk, split); 231edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 232edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 233edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOGE_IF((flags&PAGE_ALIGNED) && 234edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project ((free_chunk->start*kMemoryAlign)&(pagesize-1)), 235edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project "PAGE_ALIGNED requested, but page is not aligned!!!"); 236edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 237edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const ssize_t tail_free = free_size - (size+extra); 238edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (tail_free > 0) { 239edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* split = new chunk_t( 240edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project free_chunk->start + free_chunk->size, tail_free); 241edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mList.insertAfter(free_chunk, split); 242edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 243edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 244edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return (free_chunk->start)*kMemoryAlign; 245edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 246edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return NO_MEMORY; 247edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 248edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 249edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) 250edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 251edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project start = start / kMemoryAlign; 252edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* cur = mList.head(); 253edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project while (cur) { 254edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (cur->start == start) { 255edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOG_FATAL_IF(cur->free, 256edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project "block at offset 0x%08lX of size 0x%08lX already freed", 257edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur->start*kMemoryAlign, cur->size*kMemoryAlign); 258edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 259edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // merge freed blocks together 260edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* freed = cur; 261edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur->free = 1; 262edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project do { 263edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* const p = cur->prev; 264edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* const n = cur->next; 265edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (p && (p->free || !cur->size)) { 266edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project freed = p; 267edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project p->size += cur->size; 268edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mList.remove(cur); 269edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project delete cur; 270edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 271edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur = n; 272edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } while (cur && cur->free); 273edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 274edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project #ifndef NDEBUG 275edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (!freed->free) { 276edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dump_l("dealloc (!freed->free)"); 277edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 278edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project #endif 279edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOG_FATAL_IF(!freed->free, 280edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project "freed block at offset 0x%08lX of size 0x%08lX is not free!", 281edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project freed->start * kMemoryAlign, freed->size * kMemoryAlign); 282edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 283edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return freed; 284edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 285edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur = cur->next; 286edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 287edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return 0; 288edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 289edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 290edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid SimpleBestFitAllocator::dump(const char* what, uint32_t flags) const 291edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 292edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Mutex::Autolock _l(mLock); 293edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dump_l(what, flags); 294edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 295edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 296edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid SimpleBestFitAllocator::dump_l(const char* what, uint32_t flags) const 297edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 298edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project String8 result; 299edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dump_l(result, what, flags); 300edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOGD("%s", result.string()); 301edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 302edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 303edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid SimpleBestFitAllocator::dump(String8& result, 304edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const char* what, uint32_t flags) const 305edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 306edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Mutex::Autolock _l(mLock); 307edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dump_l(result, what, flags); 308edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 309edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 310edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid SimpleBestFitAllocator::dump_l(String8& result, 311edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const char* what, uint32_t flags) const 312edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 313edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t size = 0; 314edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int32_t i = 0; 315edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t const* cur = mList.head(); 316edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 317edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const size_t SIZE = 256; 318edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project char buffer[SIZE]; 319edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project snprintf(buffer, SIZE, " %s (%p, size=%u)\n", 320edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project what, this, (unsigned int)mHeapSize); 321edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 322edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project result.append(buffer); 323edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 324edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project while (cur) { 325edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const char* errs[] = {"", "| link bogus NP", 326edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project "| link bogus PN", "| link bogus NP+PN" }; 327edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int np = ((cur->next) && cur->next->prev != cur) ? 1 : 0; 328edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int pn = ((cur->prev) && cur->prev->next != cur) ? 2 : 0; 329edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 330edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project snprintf(buffer, SIZE, " %3u: %08x | 0x%08X | 0x%08X | %s %s\n", 331edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project i, int(cur), int(cur->start*kMemoryAlign), 332edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int(cur->size*kMemoryAlign), 333edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int(cur->free) ? "F" : "A", 334edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project errs[np|pn]); 335edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 336edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project result.append(buffer); 337edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 338edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (!cur->free) 339edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size += cur->size*kMemoryAlign; 340edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 341edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project i++; 342edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur = cur->next; 343edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 344edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project snprintf(buffer, SIZE, " size allocated: %u (%u KB)\n", int(size), int(size/1024)); 345edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project result.append(buffer); 346edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 347edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 348edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 349edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 35083c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias AgopianSharedHeap::SharedHeap() 35183c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian : HeapInterface(), MemoryHeapBase() 35283c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian{ 35383c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian} 354edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 355edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSharedHeap::SharedHeap(size_t size, uint32_t flags, char const * name) 356edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : MemoryHeapBase(size, flags, name) 357edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 358edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 359edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 360edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSharedHeap::~SharedHeap() 361edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 362edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 363edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 364edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsp<IMemory> SharedHeap::mapMemory(size_t offset, size_t size) 365edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 366edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return new SimpleMemory(this, offset, size); 367edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 368edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 369edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 370edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleMemory::SimpleMemory(const sp<IMemoryHeap>& heap, 371edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project ssize_t offset, size_t size) 372edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : MemoryBase(heap, offset, size) 373edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 374edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#ifndef NDEBUG 375edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project void* const start_ptr = (void*)(intptr_t(heap->base()) + offset); 376edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project memset(start_ptr, 0xda, size); 377edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif 378edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 379edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 380edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleMemory::~SimpleMemory() 381edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 382edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t freedOffset = getOffset(); 383edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t freedSize = getSize(); 384edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 385edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // keep the size to unmap in excess 386edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t pagesize = getpagesize(); 387edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t start = freedOffset; 388edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t end = start + freedSize; 389edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project start &= ~(pagesize-1); 390edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project end = (end + pagesize-1) & ~(pagesize-1); 391edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 392edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // give back to the kernel the pages we don't need 393edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t free_start = freedOffset; 394edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t free_end = free_start + freedSize; 395edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (start < free_start) 396edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project start = free_start; 397edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (end > free_end) 398edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project end = free_end; 399edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project start = (start + pagesize-1) & ~(pagesize-1); 400edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project end &= ~(pagesize-1); 401edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 402edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (start < end) { 403edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start); 404edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t size = end-start; 405edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 406edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#ifndef NDEBUG 407edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project memset(start_ptr, 0xdf, size); 408edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif 409edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 410edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // MADV_REMOVE is not defined on Dapper based Goobuntu 411edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#ifdef MADV_REMOVE 412edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (size) { 413edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int err = madvise(start_ptr, size, MADV_REMOVE); 414edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s", 415edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project start_ptr, size, err<0 ? strerror(errno) : "Ok"); 416edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 417edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif 418edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 419edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 420edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 421edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}; // namespace android 422