| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2007 The Android Open Source Project | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
|  | 17 | #ifndef ANDROID_MEMORY_DEALER_H | 
|  | 18 | #define ANDROID_MEMORY_DEALER_H | 
|  | 19 |  | 
|  | 20 |  | 
|  | 21 | #include <stdint.h> | 
|  | 22 | #include <sys/types.h> | 
|  | 23 |  | 
|  | 24 | #include <utils/IMemory.h> | 
|  | 25 | #include <utils/threads.h> | 
|  | 26 | #include <utils/MemoryHeapBase.h> | 
|  | 27 |  | 
|  | 28 | namespace android { | 
|  | 29 | // ---------------------------------------------------------------------------- | 
|  | 30 | class String8; | 
|  | 31 |  | 
|  | 32 | /* | 
|  | 33 | * interface for implementing a "heap". A heap basically provides | 
|  | 34 | * the IMemoryHeap interface for cross-process sharing and the | 
|  | 35 | * ability to map/unmap pages within the heap. | 
|  | 36 | */ | 
|  | 37 | class HeapInterface : public virtual BnMemoryHeap | 
|  | 38 | { | 
|  | 39 | public: | 
|  | 40 | // all values must be page-aligned | 
|  | 41 | virtual sp<IMemory> mapMemory(size_t offset, size_t size) = 0; | 
|  | 42 | }; | 
|  | 43 |  | 
|  | 44 | // ---------------------------------------------------------------------------- | 
|  | 45 |  | 
|  | 46 | /* | 
|  | 47 | * interface for implementing an allocator. An allocator provides | 
|  | 48 | * methods for allocating and freeing memory blocks and dumping | 
|  | 49 | * its state. | 
|  | 50 | */ | 
|  | 51 | class AllocatorInterface : public RefBase | 
|  | 52 | { | 
|  | 53 | public: | 
|  | 54 | enum { | 
|  | 55 | PAGE_ALIGNED = 0x00000001 | 
|  | 56 | }; | 
|  | 57 |  | 
|  | 58 | virtual size_t      allocate(size_t size, uint32_t flags = 0) = 0; | 
|  | 59 | virtual status_t    deallocate(size_t offset) = 0; | 
|  | 60 | virtual size_t      size() const = 0; | 
|  | 61 | virtual void        dump(const char* what, uint32_t flags = 0) const = 0; | 
|  | 62 | virtual void        dump(String8& res, | 
|  | 63 | const char* what, uint32_t flags = 0) const = 0; | 
|  | 64 | }; | 
|  | 65 |  | 
|  | 66 | // ---------------------------------------------------------------------------- | 
|  | 67 |  | 
|  | 68 | /* | 
|  | 69 | * concrete implementation of HeapInterface on top of mmap() | 
|  | 70 | */ | 
|  | 71 | class SharedHeap : public HeapInterface, public MemoryHeapBase | 
|  | 72 | { | 
|  | 73 | public: | 
|  | 74 | SharedHeap(size_t size, uint32_t flags = 0, char const * name = NULL); | 
|  | 75 | virtual             ~SharedHeap(); | 
|  | 76 | virtual sp<IMemory> mapMemory(size_t offset, size_t size); | 
|  | 77 | }; | 
|  | 78 |  | 
|  | 79 | // ---------------------------------------------------------------------------- | 
|  | 80 |  | 
|  | 81 | /* | 
|  | 82 | * A simple templatized doubly linked-list implementation | 
|  | 83 | */ | 
|  | 84 |  | 
|  | 85 | template <typename NODE> | 
|  | 86 | class LinkedList | 
|  | 87 | { | 
|  | 88 | NODE*  mFirst; | 
|  | 89 | NODE*  mLast; | 
|  | 90 |  | 
|  | 91 | public: | 
|  | 92 | LinkedList() : mFirst(0), mLast(0) { } | 
|  | 93 | bool        isEmpty() const { return mFirst == 0; } | 
|  | 94 | NODE const* head() const { return mFirst; } | 
|  | 95 | NODE*       head() { return mFirst; } | 
|  | 96 | NODE const* tail() const { return mLast; } | 
|  | 97 | NODE*       tail() { return mLast; } | 
|  | 98 |  | 
|  | 99 | void insertAfter(NODE* node, NODE* newNode) { | 
|  | 100 | newNode->prev = node; | 
|  | 101 | newNode->next = node->next; | 
|  | 102 | if (node->next == 0) mLast = newNode; | 
|  | 103 | else                 node->next->prev = newNode; | 
|  | 104 | node->next = newNode; | 
|  | 105 | } | 
|  | 106 |  | 
|  | 107 | void insertBefore(NODE* node, NODE* newNode) { | 
|  | 108 | newNode->prev = node->prev; | 
|  | 109 | newNode->next = node; | 
|  | 110 | if (node->prev == 0)   mFirst = newNode; | 
|  | 111 | else                   node->prev->next = newNode; | 
|  | 112 | node->prev = newNode; | 
|  | 113 | } | 
|  | 114 |  | 
|  | 115 | void insertHead(NODE* newNode) { | 
|  | 116 | if (mFirst == 0) { | 
|  | 117 | mFirst = mLast = newNode; | 
|  | 118 | newNode->prev = newNode->next = 0; | 
|  | 119 | } else { | 
|  | 120 | insertBefore(mFirst, newNode); | 
|  | 121 | } | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | void insertTail(NODE* newNode) { | 
|  | 125 | if (mLast == 0) insertBeginning(newNode); | 
|  | 126 | else            insertAfter(mLast, newNode); | 
|  | 127 | } | 
|  | 128 |  | 
|  | 129 | NODE* remove(NODE* node) { | 
|  | 130 | if (node->prev == 0)    mFirst = node->next; | 
|  | 131 | else                    node->prev->next = node->next; | 
|  | 132 | if (node->next == 0)    mLast = node->prev; | 
|  | 133 | else                    node->next->prev = node->prev; | 
|  | 134 | return node; | 
|  | 135 | } | 
|  | 136 | }; | 
|  | 137 |  | 
|  | 138 |  | 
|  | 139 | /* | 
|  | 140 | * concrete implementation of AllocatorInterface using a simple | 
|  | 141 | * best-fit allocation scheme | 
|  | 142 | */ | 
|  | 143 | class SimpleBestFitAllocator : public AllocatorInterface | 
|  | 144 | { | 
|  | 145 | public: | 
|  | 146 |  | 
|  | 147 | SimpleBestFitAllocator(size_t size); | 
|  | 148 | virtual             ~SimpleBestFitAllocator(); | 
|  | 149 |  | 
|  | 150 | virtual size_t      allocate(size_t size, uint32_t flags = 0); | 
|  | 151 | virtual status_t    deallocate(size_t offset); | 
|  | 152 | virtual size_t      size() const; | 
|  | 153 | virtual void        dump(const char* what, uint32_t flags = 0) const; | 
|  | 154 | virtual void        dump(String8& res, | 
|  | 155 | const char* what, uint32_t flags = 0) const; | 
|  | 156 |  | 
|  | 157 | private: | 
|  | 158 |  | 
|  | 159 | struct chunk_t { | 
|  | 160 | chunk_t(size_t start, size_t size) | 
|  | 161 | : start(start), size(size), free(1), prev(0), next(0) { | 
|  | 162 | } | 
|  | 163 | size_t              start; | 
|  | 164 | size_t              size : 28; | 
|  | 165 | int                 free : 4; | 
|  | 166 | mutable chunk_t*    prev; | 
|  | 167 | mutable chunk_t*    next; | 
|  | 168 | }; | 
|  | 169 |  | 
|  | 170 | ssize_t  alloc(size_t size, uint32_t flags); | 
|  | 171 | chunk_t* dealloc(size_t start); | 
|  | 172 | void     dump_l(const char* what, uint32_t flags = 0) const; | 
|  | 173 | void     dump_l(String8& res, const char* what, uint32_t flags = 0) const; | 
|  | 174 |  | 
|  | 175 | static const int    kMemoryAlign; | 
|  | 176 | mutable Mutex       mLock; | 
|  | 177 | LinkedList<chunk_t> mList; | 
|  | 178 | size_t              mHeapSize; | 
|  | 179 | }; | 
|  | 180 |  | 
|  | 181 | // ---------------------------------------------------------------------------- | 
|  | 182 |  | 
|  | 183 | class MemoryDealer : public RefBase | 
|  | 184 | { | 
|  | 185 | public: | 
|  | 186 |  | 
|  | 187 | enum { | 
|  | 188 | READ_ONLY = MemoryHeapBase::READ_ONLY, | 
|  | 189 | PAGE_ALIGNED = AllocatorInterface::PAGE_ALIGNED | 
|  | 190 | }; | 
|  | 191 |  | 
|  | 192 | // creates a memory dealer with the SharedHeap and SimpleBestFitAllocator | 
|  | 193 | MemoryDealer(size_t size, uint32_t flags = 0, const char* name = 0); | 
|  | 194 |  | 
|  | 195 | // provide a custom heap but use the SimpleBestFitAllocator | 
|  | 196 | MemoryDealer(const sp<HeapInterface>& heap); | 
|  | 197 |  | 
|  | 198 | // provide both custom heap and allocotar | 
|  | 199 | MemoryDealer( | 
|  | 200 | const sp<HeapInterface>& heap, | 
|  | 201 | const sp<AllocatorInterface>& allocator); | 
|  | 202 |  | 
|  | 203 | virtual ~MemoryDealer(); | 
|  | 204 |  | 
|  | 205 | virtual sp<IMemory> allocate(size_t size, uint32_t flags = 0); | 
|  | 206 | virtual void        deallocate(size_t offset); | 
|  | 207 | virtual void        dump(const char* what, uint32_t flags = 0) const; | 
|  | 208 |  | 
|  | 209 |  | 
|  | 210 | sp<IMemoryHeap> getMemoryHeap() const { return heap(); } | 
|  | 211 | sp<AllocatorInterface> getAllocator() const { return allocator(); } | 
|  | 212 |  | 
|  | 213 | private: | 
|  | 214 | const sp<HeapInterface>&        heap() const; | 
|  | 215 | const sp<AllocatorInterface>&   allocator() const; | 
|  | 216 |  | 
|  | 217 | class Allocation : public BnMemory { | 
|  | 218 | public: | 
|  | 219 | Allocation(const sp<MemoryDealer>& dealer, | 
|  | 220 | ssize_t offset, size_t size, const sp<IMemory>& memory); | 
|  | 221 | virtual ~Allocation(); | 
|  | 222 | virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const; | 
|  | 223 | private: | 
|  | 224 | sp<MemoryDealer>        mDealer; | 
|  | 225 | ssize_t                 mOffset; | 
|  | 226 | size_t                  mSize; | 
|  | 227 | sp<IMemory>             mMemory; | 
|  | 228 | }; | 
|  | 229 |  | 
|  | 230 | sp<HeapInterface>           mHeap; | 
|  | 231 | sp<AllocatorInterface>      mAllocator; | 
|  | 232 | }; | 
|  | 233 |  | 
|  | 234 |  | 
|  | 235 | // ---------------------------------------------------------------------------- | 
|  | 236 | }; // namespace android | 
|  | 237 |  | 
|  | 238 | #endif // ANDROID_MEMORY_DEALER_H |