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