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>
200dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian#include <binder/IPCThreadState.h>
210dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian#include <binder/MemoryBase.h>
22edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/Log.h>
24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/SortedVector.h>
25edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <utils/String8.h>
260dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian#include <utils/threads.h>
27edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
28edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdint.h>
29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdio.h>
30edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdlib.h>
31edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <fcntl.h>
32edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <unistd.h>
33edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <errno.h>
34edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <string.h>
35edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
36edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/stat.h>
37edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/types.h>
38edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/mman.h>
39edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/file.h>
40edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
41edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectnamespace android {
4283c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian// ----------------------------------------------------------------------------
43edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
440dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian/*
450dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian * A simple templatized doubly linked-list implementation
460dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian */
470dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
480dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopiantemplate <typename NODE>
490dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianclass LinkedList
500dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian{
510dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    NODE*  mFirst;
520dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    NODE*  mLast;
5383c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian
540dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianpublic:
550dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian                LinkedList() : mFirst(0), mLast(0) { }
560dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    bool        isEmpty() const { return mFirst == 0; }
570dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    NODE const* head() const { return mFirst; }
580dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    NODE*       head() { return mFirst; }
590dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    NODE const* tail() const { return mLast; }
600dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    NODE*       tail() { return mLast; }
610dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
620dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    void insertAfter(NODE* node, NODE* newNode) {
630dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        newNode->prev = node;
640dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        newNode->next = node->next;
650dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        if (node->next == 0) mLast = newNode;
660dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        else                 node->next->prev = newNode;
670dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        node->next = newNode;
680dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    }
6983c0446f27b9542d6c2e724817b2b2d8d1f55085Mathias Agopian
700dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    void insertBefore(NODE* node, NODE* newNode) {
710dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian         newNode->prev = node->prev;
720dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian         newNode->next = node;
730dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian         if (node->prev == 0)   mFirst = newNode;
740dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian         else                   node->prev->next = newNode;
750dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian         node->prev = newNode;
760dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    }
770dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
780dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    void insertHead(NODE* newNode) {
790dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        if (mFirst == 0) {
800dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            mFirst = mLast = newNode;
810dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            newNode->prev = newNode->next = 0;
820dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        } else {
830dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            newNode->prev = 0;
840dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            newNode->next = mFirst;
850dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            mFirst->prev = newNode;
860dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            mFirst = newNode;
870dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        }
880dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    }
890dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
900dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    void insertTail(NODE* newNode) {
910dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        if (mLast == 0) {
920dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            insertHead(newNode);
930dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        } else {
940dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            newNode->prev = mLast;
950dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            newNode->next = 0;
960dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            mLast->next = newNode;
970dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            mLast = newNode;
980dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        }
990dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    }
1000dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
1010dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    NODE* remove(NODE* node) {
1020dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        if (node->prev == 0)    mFirst = node->next;
1030dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        else                    node->prev->next = node->next;
1040dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        if (node->next == 0)    mLast = node->prev;
1050dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        else                    node->next->prev = node->prev;
1060dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        return node;
1070dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    }
1080dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian};
109edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
110edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
111edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
1120dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianclass Allocation : public MemoryBase {
113edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectpublic:
1140dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    Allocation(const sp<MemoryDealer>& dealer,
1150dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
1160dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    virtual ~Allocation();
1170dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianprivate:
1180dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    sp<MemoryDealer> mDealer;
119edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project};
120edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
1210dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian// ----------------------------------------------------------------------------
1220dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
1230dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianclass SimpleBestFitAllocator
1240dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian{
1250dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    enum {
1260dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        PAGE_ALIGNED = 0x00000001
1270dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    };
1280dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianpublic:
129e2347b7953f70232541bdc1b392230d6231aaeb9Chih-Hung Hsieh    explicit SimpleBestFitAllocator(size_t size);
1300dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    ~SimpleBestFitAllocator();
1310dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
1320dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    size_t      allocate(size_t size, uint32_t flags = 0);
1330dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    status_t    deallocate(size_t offset);
1340dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    size_t      size() const;
1350dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    void        dump(const char* what) const;
1360dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    void        dump(String8& res, const char* what) const;
1370dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
1381001033cbede0196aa020102f6fd4f6796089cd5Lajos Molnar    static size_t getAllocationAlignment() { return kMemoryAlign; }
1391001033cbede0196aa020102f6fd4f6796089cd5Lajos Molnar
1400dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianprivate:
1410dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
1420dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    struct chunk_t {
1430dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        chunk_t(size_t start, size_t size)
1440dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        : start(start), size(size), free(1), prev(0), next(0) {
1450dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        }
1460dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        size_t              start;
1470dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        size_t              size : 28;
1480dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        int                 free : 4;
1490dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        mutable chunk_t*    prev;
1500dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        mutable chunk_t*    next;
1510dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    };
1520dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
1530dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    ssize_t  alloc(size_t size, uint32_t flags);
1540dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    chunk_t* dealloc(size_t start);
1550dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    void     dump_l(const char* what) const;
1560dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    void     dump_l(String8& res, const char* what) const;
1570dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
1580dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    static const int    kMemoryAlign;
1590dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    mutable Mutex       mLock;
1600dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    LinkedList<chunk_t> mList;
1610dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    size_t              mHeapSize;
1620dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian};
163edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
164edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
165edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
1660dd0d2944a0a7b985db162dec8b49b77d689d171Mathias AgopianAllocation::Allocation(
1670dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        const sp<MemoryDealer>& dealer,
1680dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        const sp<IMemoryHeap>& heap, ssize_t offset, size_t size)
1690dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    : MemoryBase(heap, offset, size), mDealer(dealer)
170edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
1710dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian#ifndef NDEBUG
1720dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    void* const start_ptr = (void*)(intptr_t(heap->base()) + offset);
1730dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    memset(start_ptr, 0xda, size);
1740dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian#endif
175edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
176edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
1770dd0d2944a0a7b985db162dec8b49b77d689d171Mathias AgopianAllocation::~Allocation()
178edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
1790dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    size_t freedOffset = getOffset();
1800dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    size_t freedSize   = getSize();
1810dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    if (freedSize) {
182edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        /* NOTE: it's VERY important to not free allocations of size 0 because
183edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project         * they're special as they don't have any record in the allocator
184edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project         * and could alias some real allocation (their offset is zero). */
1850dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
1860dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        // keep the size to unmap in excess
1870dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        size_t pagesize = getpagesize();
1880dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        size_t start = freedOffset;
1890dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        size_t end = start + freedSize;
1900dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        start &= ~(pagesize-1);
1910dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        end = (end + pagesize-1) & ~(pagesize-1);
1920dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
1930dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        // give back to the kernel the pages we don't need
1940dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        size_t free_start = freedOffset;
1950dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        size_t free_end = free_start + freedSize;
1960dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        if (start < free_start)
1970dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            start = free_start;
1980dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        if (end > free_end)
1990dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            end = free_end;
2000dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        start = (start + pagesize-1) & ~(pagesize-1);
2010dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        end &= ~(pagesize-1);
2020dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
2030dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        if (start < end) {
2040dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start);
2050dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            size_t size = end-start;
206edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
2070dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian#ifndef NDEBUG
2080dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            memset(start_ptr, 0xdf, size);
2090dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian#endif
2100dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian
2110dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            // MADV_REMOVE is not defined on Dapper based Goobuntu
2120dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian#ifdef MADV_REMOVE
2130dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            if (size) {
2140dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian                int err = madvise(start_ptr, size, MADV_REMOVE);
2156f4f3ab36c5ed1df84eb3a9f7475f0ac42952f58Colin Cross                ALOGW_IF(err, "madvise(%p, %zu, MADV_REMOVE) returned %s",
2160dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian                        start_ptr, size, err<0 ? strerror(errno) : "Ok");
2170dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            }
2180dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian#endif
2190dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        }
220c4cd5301d4978dda5266194625ef4fd7f9d3dde4Ji-Hwan Lee
221c4cd5301d4978dda5266194625ef4fd7f9d3dde4Ji-Hwan Lee        // This should be done after madvise(MADV_REMOVE), otherwise madvise()
222c4cd5301d4978dda5266194625ef4fd7f9d3dde4Ji-Hwan Lee        // might kick out the memory region that's allocated and/or written
223c4cd5301d4978dda5266194625ef4fd7f9d3dde4Ji-Hwan Lee        // right after the deallocation.
224c4cd5301d4978dda5266194625ef4fd7f9d3dde4Ji-Hwan Lee        mDealer->deallocate(freedOffset);
2250dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    }
226edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
227edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
228edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
229edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
2306546f2e45861172af83b0c1e6432cae24e97d4ccGlenn KastenMemoryDealer::MemoryDealer(size_t size, const char* name, uint32_t flags)
2316546f2e45861172af83b0c1e6432cae24e97d4ccGlenn Kasten    : mHeap(new MemoryHeapBase(size, flags, name)),
232edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mAllocator(new SimpleBestFitAllocator(size))
233edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
234edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
235edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
236edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectMemoryDealer::~MemoryDealer()
237edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
2380dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    delete mAllocator;
239edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
240edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
2410dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopiansp<IMemory> MemoryDealer::allocate(size_t size)
242edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
243edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    sp<IMemory> memory;
2440dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    const ssize_t offset = allocator()->allocate(size);
245edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (offset >= 0) {
2460dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        memory = new Allocation(this, heap(), offset, size);
247edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
248edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return memory;
249edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
250edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
251edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid MemoryDealer::deallocate(size_t offset)
252edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
253edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    allocator()->deallocate(offset);
254edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
255edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
2560dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianvoid MemoryDealer::dump(const char* what) const
257edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
2580dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    allocator()->dump(what);
259edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
260edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
2610dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianconst sp<IMemoryHeap>& MemoryDealer::heap() const {
262edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return mHeap;
263edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
264edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
2650dd0d2944a0a7b985db162dec8b49b77d689d171Mathias AgopianSimpleBestFitAllocator* MemoryDealer::allocator() const {
266edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return mAllocator;
267edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
268edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
2691001033cbede0196aa020102f6fd4f6796089cd5Lajos Molnar// static
2701001033cbede0196aa020102f6fd4f6796089cd5Lajos Molnarsize_t MemoryDealer::getAllocationAlignment()
2711001033cbede0196aa020102f6fd4f6796089cd5Lajos Molnar{
2721001033cbede0196aa020102f6fd4f6796089cd5Lajos Molnar    return SimpleBestFitAllocator::getAllocationAlignment();
2731001033cbede0196aa020102f6fd4f6796089cd5Lajos Molnar}
2741001033cbede0196aa020102f6fd4f6796089cd5Lajos Molnar
275edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ----------------------------------------------------------------------------
276edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
277edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// align all the memory blocks on a cache-line boundary
278edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectconst int SimpleBestFitAllocator::kMemoryAlign = 32;
279edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
280edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleBestFitAllocator::SimpleBestFitAllocator(size_t size)
281edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
282edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    size_t pagesize = getpagesize();
283edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mHeapSize = ((size + pagesize-1) & ~(pagesize-1));
284edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
285edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign);
286edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    mList.insertHead(node);
287edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
288edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
289edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleBestFitAllocator::~SimpleBestFitAllocator()
290edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
291edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    while(!mList.isEmpty()) {
292edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        delete mList.remove(mList.head());
293edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
294edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
295edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
296edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsize_t SimpleBestFitAllocator::size() const
297edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
298edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return mHeapSize;
299edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
300edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
301edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectsize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags)
302edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
303edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Mutex::Autolock _l(mLock);
304edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    ssize_t offset = alloc(size, flags);
305edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return offset;
306edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
307edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
308edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t SimpleBestFitAllocator::deallocate(size_t offset)
309edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
310edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Mutex::Autolock _l(mLock);
311edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    chunk_t const * const freed = dealloc(offset);
312edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (freed) {
313edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return NO_ERROR;
314edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
315edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return NAME_NOT_FOUND;
316edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
317edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
318edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
319edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
320edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (size == 0) {
321edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return 0;
322edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
323edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    size = (size + kMemoryAlign-1) / kMemoryAlign;
324edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    chunk_t* free_chunk = 0;
325edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    chunk_t* cur = mList.head();
326edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
327edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    size_t pagesize = getpagesize();
328edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    while (cur) {
329edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        int extra = 0;
330edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (flags & PAGE_ALIGNED)
331edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ;
332edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
333edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        // best fit
334edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (cur->free && (cur->size >= (size+extra))) {
335edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if ((!free_chunk) || (cur->size < free_chunk->size)) {
336edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                free_chunk = cur;
337edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
338edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (cur->size == size) {
339edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                break;
340edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
341edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
342edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        cur = cur->next;
343edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
344edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
345edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    if (free_chunk) {
346edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const size_t free_size = free_chunk->size;
347edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        free_chunk->free = 0;
348edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        free_chunk->size = size;
349edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (free_size > size) {
350edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int extra = 0;
351edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (flags & PAGE_ALIGNED)
352edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ;
353edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (extra) {
354edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                chunk_t* split = new chunk_t(free_chunk->start, extra);
355edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                free_chunk->start += extra;
356edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                mList.insertBefore(free_chunk, split);
357edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
358edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
359e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block            ALOGE_IF((flags&PAGE_ALIGNED) &&
360edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    ((free_chunk->start*kMemoryAlign)&(pagesize-1)),
361edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    "PAGE_ALIGNED requested, but page is not aligned!!!");
362edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
363edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            const ssize_t tail_free = free_size - (size+extra);
364edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            if (tail_free > 0) {
365edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                chunk_t* split = new chunk_t(
366edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                        free_chunk->start + free_chunk->size, tail_free);
367edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                mList.insertAfter(free_chunk, split);
368edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            }
369edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
370edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        return (free_chunk->start)*kMemoryAlign;
371edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
372edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return NO_MEMORY;
373edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
374edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
375edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectSimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
376edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
377edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    start = start / kMemoryAlign;
378edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    chunk_t* cur = mList.head();
379edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    while (cur) {
380edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (cur->start == start) {
381edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            LOG_FATAL_IF(cur->free,
382edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                "block at offset 0x%08lX of size 0x%08lX already freed",
383edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                cur->start*kMemoryAlign, cur->size*kMemoryAlign);
384edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
385edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            // merge freed blocks together
386edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            chunk_t* freed = cur;
387edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            cur->free = 1;
388edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            do {
389edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                chunk_t* const p = cur->prev;
390edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                chunk_t* const n = cur->next;
391edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                if (p && (p->free || !cur->size)) {
392edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    freed = p;
393edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    p->size += cur->size;
394edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    mList.remove(cur);
395edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    delete cur;
396edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                }
397edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                cur = n;
398edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            } while (cur && cur->free);
399edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
400edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            #ifndef NDEBUG
401edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                if (!freed->free) {
402edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    dump_l("dealloc (!freed->free)");
403edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                }
404edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            #endif
405edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            LOG_FATAL_IF(!freed->free,
406edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                "freed block at offset 0x%08lX of size 0x%08lX is not free!",
407edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                freed->start * kMemoryAlign, freed->size * kMemoryAlign);
408edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
409edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            return freed;
410edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
411edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        cur = cur->next;
412edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
413edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    return 0;
414edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
415edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
4160dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianvoid SimpleBestFitAllocator::dump(const char* what) const
417edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
418edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Mutex::Autolock _l(mLock);
4190dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    dump_l(what);
420edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
421edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
4220dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopianvoid SimpleBestFitAllocator::dump_l(const char* what) const
423edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
424edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    String8 result;
4250dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    dump_l(result, what);
4269d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block    ALOGD("%s", result.string());
427edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
428edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
429edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid SimpleBestFitAllocator::dump(String8& result,
4300dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        const char* what) const
431edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
432edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Mutex::Autolock _l(mLock);
4330dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    dump_l(result, what);
434edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
435edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
436edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid SimpleBestFitAllocator::dump_l(String8& result,
4370dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian        const char* what) const
438edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{
439edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    size_t size = 0;
440edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    int32_t i = 0;
441edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    chunk_t const* cur = mList.head();
442edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
443edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    const size_t SIZE = 256;
444edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    char buffer[SIZE];
445edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    snprintf(buffer, SIZE, "  %s (%p, size=%u)\n",
446edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            what, this, (unsigned int)mHeapSize);
447edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
448edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    result.append(buffer);
449edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
450edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    while (cur) {
451edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        const char* errs[] = {"", "| link bogus NP",
452edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                            "| link bogus PN", "| link bogus NP+PN" };
453edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        int np = ((cur->next) && cur->next->prev != cur) ? 1 : 0;
454edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        int pn = ((cur->prev) && cur->prev->next != cur) ? 2 : 0;
455edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
456f683e0163a84d93448b9388126902242367cd961Serban Constantinescu        snprintf(buffer, SIZE, "  %3u: %p | 0x%08X | 0x%08X | %s %s\n",
457f683e0163a84d93448b9388126902242367cd961Serban Constantinescu            i, cur, int(cur->start*kMemoryAlign),
458edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            int(cur->size*kMemoryAlign),
459edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    int(cur->free) ? "F" : "A",
460edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project                    errs[np|pn]);
461edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
462edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        result.append(buffer);
463edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
464edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        if (!cur->free)
465edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project            size += cur->size*kMemoryAlign;
466edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
467edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        i++;
468edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        cur = cur->next;
469edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
4700dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian    snprintf(buffer, SIZE,
4710dd0d2944a0a7b985db162dec8b49b77d689d171Mathias Agopian            "  size allocated: %u (%u KB)\n", int(size), int(size/1024));
472edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    result.append(buffer);
473edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}
474edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
475edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
476edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}; // namespace android
477