MemoryDealer.cpp revision c5b2c0bf8007562536b822eb060fc54a01f8e08b
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 { 41edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 42edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 43edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 44edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 45edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectclass SimpleMemory : public MemoryBase { 46edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectpublic: 47edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project SimpleMemory(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size); 48edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project virtual ~SimpleMemory(); 49edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}; 50edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 51edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 52edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 53edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 54edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::Allocation::Allocation( 55edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const sp<MemoryDealer>& dealer, ssize_t offset, size_t size, 56edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const sp<IMemory>& memory) 57edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : mDealer(dealer), mOffset(offset), mSize(size), mMemory(memory) 58edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 59edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 60edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 61edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::Allocation::~Allocation() 62edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 63edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (mSize) { 64edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project /* NOTE: it's VERY important to not free allocations of size 0 because 65edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * they're special as they don't have any record in the allocator 66edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * and could alias some real allocation (their offset is zero). */ 67edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mDealer->deallocate(mOffset); 68edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 69edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 70edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 71edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsp<IMemoryHeap> MemoryDealer::Allocation::getMemory( 72edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project ssize_t* offset, size_t* size) const 73edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 74edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return mMemory->getMemory(offset, size); 75edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 76edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 77edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 78edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 79edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::MemoryDealer(size_t size, uint32_t flags, const char* name) 80edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : mHeap(new SharedHeap(size, flags, name)), 81edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mAllocator(new SimpleBestFitAllocator(size)) 82edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 83edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 84edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 85edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::MemoryDealer(const sp<HeapInterface>& heap) 86edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : mHeap(heap), 87edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mAllocator(new SimpleBestFitAllocator(heap->virtualSize())) 88edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 89edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 90edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 91edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::MemoryDealer( const sp<HeapInterface>& heap, 92edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const sp<AllocatorInterface>& allocator) 93edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : mHeap(heap), mAllocator(allocator) 94edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 95edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 96edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 97edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::~MemoryDealer() 98edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 99edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 100edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 101edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsp<IMemory> MemoryDealer::allocate(size_t size, uint32_t flags) 102edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 103edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project sp<IMemory> memory; 104edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const ssize_t offset = allocator()->allocate(size, flags); 105edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (offset >= 0) { 106edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project sp<IMemory> new_memory = heap()->mapMemory(offset, size); 107edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (new_memory != 0) { 108edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project memory = new Allocation(this, offset, size, new_memory); 109edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } else { 110edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOGE("couldn't map [%8x, %d]", offset, size); 111edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (size) { 112edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project /* NOTE: it's VERY important to not free allocations of size 0 113edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * because they're special as they don't have any record in the 114edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * allocator and could alias some real allocation 115edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * (their offset is zero). */ 116edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project allocator()->deallocate(offset); 117edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 118edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 119edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 120edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return memory; 121edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 122edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 123edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid MemoryDealer::deallocate(size_t offset) 124edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 125edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project allocator()->deallocate(offset); 126edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 127edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 128edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid MemoryDealer::dump(const char* what, uint32_t flags) const 129edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 130edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project allocator()->dump(what, flags); 131edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 132edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 133edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectconst sp<HeapInterface>& MemoryDealer::heap() const { 134edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return mHeap; 135edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 136edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 137edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectconst sp<AllocatorInterface>& MemoryDealer::allocator() const { 138edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return mAllocator; 139edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 140edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 141edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 142edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 143edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// align all the memory blocks on a cache-line boundary 144edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectconst int SimpleBestFitAllocator::kMemoryAlign = 32; 145edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 146edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) 147edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 148edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t pagesize = getpagesize(); 149edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); 150edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 151edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); 152edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mList.insertHead(node); 153edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 154edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 155edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleBestFitAllocator::~SimpleBestFitAllocator() 156edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 157edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project while(!mList.isEmpty()) { 158edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project delete mList.remove(mList.head()); 159edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 160edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 161edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 162edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsize_t SimpleBestFitAllocator::size() const 163edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 164edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return mHeapSize; 165edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 166edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 167edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) 168edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 169edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Mutex::Autolock _l(mLock); 170edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project ssize_t offset = alloc(size, flags); 171edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return offset; 172edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 173edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 174edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t SimpleBestFitAllocator::deallocate(size_t offset) 175edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 176edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Mutex::Autolock _l(mLock); 177edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t const * const freed = dealloc(offset); 178edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (freed) { 179edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return NO_ERROR; 180edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 181edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return NAME_NOT_FOUND; 182edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 183edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 184edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) 185edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 186edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (size == 0) { 187edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return 0; 188edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 189edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size = (size + kMemoryAlign-1) / kMemoryAlign; 190edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* free_chunk = 0; 191edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* cur = mList.head(); 192edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 193edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t pagesize = getpagesize(); 194edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project while (cur) { 195edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int extra = 0; 196edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (flags & PAGE_ALIGNED) 197edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; 198edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 199edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // best fit 200edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (cur->free && (cur->size >= (size+extra))) { 201edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if ((!free_chunk) || (cur->size < free_chunk->size)) { 202edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project free_chunk = cur; 203edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 204edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (cur->size == size) { 205edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project break; 206edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 207edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 208edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur = cur->next; 209edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 210edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 211edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (free_chunk) { 212edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const size_t free_size = free_chunk->size; 213edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project free_chunk->free = 0; 214edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project free_chunk->size = size; 215edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (free_size > size) { 216edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int extra = 0; 217edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (flags & PAGE_ALIGNED) 218edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; 219edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (extra) { 220edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* split = new chunk_t(free_chunk->start, extra); 221edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project free_chunk->start += extra; 222edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mList.insertBefore(free_chunk, split); 223edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 224edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 225edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOGE_IF((flags&PAGE_ALIGNED) && 226edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project ((free_chunk->start*kMemoryAlign)&(pagesize-1)), 227edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project "PAGE_ALIGNED requested, but page is not aligned!!!"); 228edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 229edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const ssize_t tail_free = free_size - (size+extra); 230edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (tail_free > 0) { 231edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* split = new chunk_t( 232edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project free_chunk->start + free_chunk->size, tail_free); 233edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mList.insertAfter(free_chunk, split); 234edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 235edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 236edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return (free_chunk->start)*kMemoryAlign; 237edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 238edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return NO_MEMORY; 239edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 240edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 241edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) 242edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 243edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project start = start / kMemoryAlign; 244edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* cur = mList.head(); 245edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project while (cur) { 246edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (cur->start == start) { 247edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOG_FATAL_IF(cur->free, 248edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project "block at offset 0x%08lX of size 0x%08lX already freed", 249edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur->start*kMemoryAlign, cur->size*kMemoryAlign); 250edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 251edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // merge freed blocks together 252edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* freed = cur; 253edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur->free = 1; 254edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project do { 255edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* const p = cur->prev; 256edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t* const n = cur->next; 257edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (p && (p->free || !cur->size)) { 258edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project freed = p; 259edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project p->size += cur->size; 260edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project mList.remove(cur); 261edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project delete cur; 262edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 263edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur = n; 264edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } while (cur && cur->free); 265edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 266edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project #ifndef NDEBUG 267edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (!freed->free) { 268edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dump_l("dealloc (!freed->free)"); 269edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 270edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project #endif 271edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOG_FATAL_IF(!freed->free, 272edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project "freed block at offset 0x%08lX of size 0x%08lX is not free!", 273edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project freed->start * kMemoryAlign, freed->size * kMemoryAlign); 274edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 275edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return freed; 276edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 277edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur = cur->next; 278edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 279edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return 0; 280edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 281edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 282edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid SimpleBestFitAllocator::dump(const char* what, uint32_t flags) const 283edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 284edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Mutex::Autolock _l(mLock); 285edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dump_l(what, flags); 286edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 287edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 288edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid SimpleBestFitAllocator::dump_l(const char* what, uint32_t flags) const 289edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 290edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project String8 result; 291edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dump_l(result, what, flags); 292edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOGD("%s", result.string()); 293edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 294edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 295edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid SimpleBestFitAllocator::dump(String8& result, 296edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const char* what, uint32_t flags) const 297edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 298edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Mutex::Autolock _l(mLock); 299edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dump_l(result, what, flags); 300edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 301edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 302edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid SimpleBestFitAllocator::dump_l(String8& result, 303edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const char* what, uint32_t flags) const 304edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 305edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t size = 0; 306edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int32_t i = 0; 307edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project chunk_t const* cur = mList.head(); 308edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 309edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const size_t SIZE = 256; 310edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project char buffer[SIZE]; 311edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project snprintf(buffer, SIZE, " %s (%p, size=%u)\n", 312edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project what, this, (unsigned int)mHeapSize); 313edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 314edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project result.append(buffer); 315edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 316edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project while (cur) { 317edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const char* errs[] = {"", "| link bogus NP", 318edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project "| link bogus PN", "| link bogus NP+PN" }; 319edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int np = ((cur->next) && cur->next->prev != cur) ? 1 : 0; 320edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int pn = ((cur->prev) && cur->prev->next != cur) ? 2 : 0; 321edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 322edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project snprintf(buffer, SIZE, " %3u: %08x | 0x%08X | 0x%08X | %s %s\n", 323edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project i, int(cur), int(cur->start*kMemoryAlign), 324edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int(cur->size*kMemoryAlign), 325edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int(cur->free) ? "F" : "A", 326edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project errs[np|pn]); 327edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 328edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project result.append(buffer); 329edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 330edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (!cur->free) 331edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size += cur->size*kMemoryAlign; 332edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 333edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project i++; 334edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project cur = cur->next; 335edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 336edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project snprintf(buffer, SIZE, " size allocated: %u (%u KB)\n", int(size), int(size/1024)); 337edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project result.append(buffer); 338edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 339edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 340edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 341edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 342edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 343edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSharedHeap::SharedHeap(size_t size, uint32_t flags, char const * name) 344edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : MemoryHeapBase(size, flags, name) 345edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 346edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 347edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 348edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSharedHeap::~SharedHeap() 349edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 350edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 351edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 352edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsp<IMemory> SharedHeap::mapMemory(size_t offset, size_t size) 353edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 354edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return new SimpleMemory(this, offset, size); 355edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 356edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 357edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 358edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleMemory::SimpleMemory(const sp<IMemoryHeap>& heap, 359edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project ssize_t offset, size_t size) 360edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project : MemoryBase(heap, offset, size) 361edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 362edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#ifndef NDEBUG 363edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project void* const start_ptr = (void*)(intptr_t(heap->base()) + offset); 364edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project memset(start_ptr, 0xda, size); 365edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif 366edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 367edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 368edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleMemory::~SimpleMemory() 369edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 370edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t freedOffset = getOffset(); 371edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t freedSize = getSize(); 372edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 373edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // keep the size to unmap in excess 374edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t pagesize = getpagesize(); 375edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t start = freedOffset; 376edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t end = start + freedSize; 377edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project start &= ~(pagesize-1); 378edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project end = (end + pagesize-1) & ~(pagesize-1); 379edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 380edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // give back to the kernel the pages we don't need 381edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t free_start = freedOffset; 382edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t free_end = free_start + freedSize; 383edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (start < free_start) 384edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project start = free_start; 385edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (end > free_end) 386edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project end = free_end; 387edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project start = (start + pagesize-1) & ~(pagesize-1); 388edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project end &= ~(pagesize-1); 389edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 390edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (start < end) { 391edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start); 392edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t size = end-start; 393edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 394edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#ifndef NDEBUG 395edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project memset(start_ptr, 0xdf, size); 396edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif 397edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 398edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // MADV_REMOVE is not defined on Dapper based Goobuntu 399edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#ifdef MADV_REMOVE 400edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (size) { 401edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int err = madvise(start_ptr, size, MADV_REMOVE); 402edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s", 403edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project start_ptr, size, err<0 ? strerror(errno) : "Ok"); 404edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 405edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#endif 406edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 407edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 408edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 409edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}; // namespace android 410