MemoryDealer.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  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. #define LOG_TAG "MemoryDealer"
  17. #include <binder/MemoryDealer.h>
  18. #include <binder/IPCThreadState.h>
  19. #include <binder/MemoryBase.h>
  20. #include <utils/Log.h>
  21. #include <utils/SortedVector.h>
  22. #include <utils/String8.h>
  23. #include <utils/threads.h>
  24. #include <stdint.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <fcntl.h>
  28. #include <unistd.h>
  29. #include <errno.h>
  30. #include <string.h>
  31. #include <sys/stat.h>
  32. #include <sys/types.h>
  33. #include <sys/mman.h>
  34. #include <sys/file.h>
  35. namespace android {
  36. // ----------------------------------------------------------------------------
  37. /*
  38. * A simple templatized doubly linked-list implementation
  39. */
  40. template <typename NODE>
  41. class LinkedList
  42. {
  43. NODE* mFirst;
  44. NODE* mLast;
  45. public:
  46. LinkedList() : mFirst(nullptr), mLast(nullptr) { }
  47. bool isEmpty() const { return mFirst == nullptr; }
  48. NODE const* head() const { return mFirst; }
  49. NODE* head() { return mFirst; }
  50. NODE const* tail() const { return mLast; }
  51. NODE* tail() { return mLast; }
  52. void insertAfter(NODE* node, NODE* newNode) {
  53. newNode->prev = node;
  54. newNode->next = node->next;
  55. if (node->next == nullptr) mLast = newNode;
  56. else node->next->prev = newNode;
  57. node->next = newNode;
  58. }
  59. void insertBefore(NODE* node, NODE* newNode) {
  60. newNode->prev = node->prev;
  61. newNode->next = node;
  62. if (node->prev == nullptr) mFirst = newNode;
  63. else node->prev->next = newNode;
  64. node->prev = newNode;
  65. }
  66. void insertHead(NODE* newNode) {
  67. if (mFirst == nullptr) {
  68. mFirst = mLast = newNode;
  69. newNode->prev = newNode->next = nullptr;
  70. } else {
  71. newNode->prev = nullptr;
  72. newNode->next = mFirst;
  73. mFirst->prev = newNode;
  74. mFirst = newNode;
  75. }
  76. }
  77. void insertTail(NODE* newNode) {
  78. if (mLast == 0) {
  79. insertHead(newNode);
  80. } else {
  81. newNode->prev = mLast;
  82. newNode->next = 0;
  83. mLast->next = newNode;
  84. mLast = newNode;
  85. }
  86. }
  87. NODE* remove(NODE* node) {
  88. if (node->prev == nullptr) mFirst = node->next;
  89. else node->prev->next = node->next;
  90. if (node->next == nullptr) mLast = node->prev;
  91. else node->next->prev = node->prev;
  92. return node;
  93. }
  94. };
  95. // ----------------------------------------------------------------------------
  96. class Allocation : public MemoryBase {
  97. public:
  98. Allocation(const sp<MemoryDealer>& dealer,
  99. const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
  100. virtual ~Allocation();
  101. private:
  102. sp<MemoryDealer> mDealer;
  103. };
  104. // ----------------------------------------------------------------------------
  105. class SimpleBestFitAllocator
  106. {
  107. enum {
  108. PAGE_ALIGNED = 0x00000001
  109. };
  110. public:
  111. explicit SimpleBestFitAllocator(size_t size);
  112. ~SimpleBestFitAllocator();
  113. size_t allocate(size_t size, uint32_t flags = 0);
  114. status_t deallocate(size_t offset);
  115. size_t size() const;
  116. void dump(const char* what) const;
  117. void dump(String8& res, const char* what) const;
  118. static size_t getAllocationAlignment() { return kMemoryAlign; }
  119. private:
  120. struct chunk_t {
  121. chunk_t(size_t start, size_t size)
  122. : start(start), size(size), free(1), prev(nullptr), next(nullptr) {
  123. }
  124. size_t start;
  125. size_t size : 28;
  126. int free : 4;
  127. mutable chunk_t* prev;
  128. mutable chunk_t* next;
  129. };
  130. ssize_t alloc(size_t size, uint32_t flags);
  131. chunk_t* dealloc(size_t start);
  132. void dump_l(const char* what) const;
  133. void dump_l(String8& res, const char* what) const;
  134. static const int kMemoryAlign;
  135. mutable Mutex mLock;
  136. LinkedList<chunk_t> mList;
  137. size_t mHeapSize;
  138. };
  139. // ----------------------------------------------------------------------------
  140. Allocation::Allocation(
  141. const sp<MemoryDealer>& dealer,
  142. const sp<IMemoryHeap>& heap, ssize_t offset, size_t size)
  143. : MemoryBase(heap, offset, size), mDealer(dealer)
  144. {
  145. #ifndef NDEBUG
  146. void* const start_ptr = (void*)(intptr_t(heap->base()) + offset);
  147. memset(start_ptr, 0xda, size);
  148. #endif
  149. }
  150. Allocation::~Allocation()
  151. {
  152. size_t freedOffset = getOffset();
  153. size_t freedSize = getSize();
  154. if (freedSize) {
  155. /* NOTE: it's VERY important to not free allocations of size 0 because
  156. * they're special as they don't have any record in the allocator
  157. * and could alias some real allocation (their offset is zero). */
  158. // keep the size to unmap in excess
  159. size_t pagesize = getpagesize();
  160. size_t start = freedOffset;
  161. size_t end = start + freedSize;
  162. start &= ~(pagesize-1);
  163. end = (end + pagesize-1) & ~(pagesize-1);
  164. // give back to the kernel the pages we don't need
  165. size_t free_start = freedOffset;
  166. size_t free_end = free_start + freedSize;
  167. if (start < free_start)
  168. start = free_start;
  169. if (end > free_end)
  170. end = free_end;
  171. start = (start + pagesize-1) & ~(pagesize-1);
  172. end &= ~(pagesize-1);
  173. if (start < end) {
  174. void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start);
  175. size_t size = end-start;
  176. #ifndef NDEBUG
  177. memset(start_ptr, 0xdf, size);
  178. #endif
  179. // MADV_REMOVE is not defined on Dapper based Goobuntu
  180. #ifdef MADV_REMOVE
  181. if (size) {
  182. int err = madvise(start_ptr, size, MADV_REMOVE);
  183. ALOGW_IF(err, "madvise(%p, %zu, MADV_REMOVE) returned %s",
  184. start_ptr, size, err<0 ? strerror(errno) : "Ok");
  185. }
  186. #endif
  187. }
  188. // This should be done after madvise(MADV_REMOVE), otherwise madvise()
  189. // might kick out the memory region that's allocated and/or written
  190. // right after the deallocation.
  191. mDealer->deallocate(freedOffset);
  192. }
  193. }
  194. // ----------------------------------------------------------------------------
  195. MemoryDealer::MemoryDealer(size_t size, const char* name, uint32_t flags)
  196. : mHeap(new MemoryHeapBase(size, flags, name)),
  197. mAllocator(new SimpleBestFitAllocator(size))
  198. {
  199. }
  200. MemoryDealer::~MemoryDealer()
  201. {
  202. delete mAllocator;
  203. }
  204. sp<IMemory> MemoryDealer::allocate(size_t size)
  205. {
  206. sp<IMemory> memory;
  207. const ssize_t offset = allocator()->allocate(size);
  208. if (offset >= 0) {
  209. memory = new Allocation(this, heap(), offset, size);
  210. }
  211. return memory;
  212. }
  213. void MemoryDealer::deallocate(size_t offset)
  214. {
  215. allocator()->deallocate(offset);
  216. }
  217. void MemoryDealer::dump(const char* what) const
  218. {
  219. allocator()->dump(what);
  220. }
  221. const sp<IMemoryHeap>& MemoryDealer::heap() const {
  222. return mHeap;
  223. }
  224. SimpleBestFitAllocator* MemoryDealer::allocator() const {
  225. return mAllocator;
  226. }
  227. // static
  228. size_t MemoryDealer::getAllocationAlignment()
  229. {
  230. return SimpleBestFitAllocator::getAllocationAlignment();
  231. }
  232. // ----------------------------------------------------------------------------
  233. // align all the memory blocks on a cache-line boundary
  234. const int SimpleBestFitAllocator::kMemoryAlign = 32;
  235. SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size)
  236. {
  237. size_t pagesize = getpagesize();
  238. mHeapSize = ((size + pagesize-1) & ~(pagesize-1));
  239. chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign);
  240. mList.insertHead(node);
  241. }
  242. SimpleBestFitAllocator::~SimpleBestFitAllocator()
  243. {
  244. while(!mList.isEmpty()) {
  245. chunk_t* removed = mList.remove(mList.head());
  246. #ifdef __clang_analyzer__
  247. // Clang static analyzer gets confused in this loop
  248. // and generates a false positive warning about accessing
  249. // memory that is already freed.
  250. // Add an "assert" to avoid the confusion.
  251. LOG_ALWAYS_FATAL_IF(mList.head() == removed);
  252. #endif
  253. delete removed;
  254. }
  255. }
  256. size_t SimpleBestFitAllocator::size() const
  257. {
  258. return mHeapSize;
  259. }
  260. size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags)
  261. {
  262. Mutex::Autolock _l(mLock);
  263. ssize_t offset = alloc(size, flags);
  264. return offset;
  265. }
  266. status_t SimpleBestFitAllocator::deallocate(size_t offset)
  267. {
  268. Mutex::Autolock _l(mLock);
  269. chunk_t const * const freed = dealloc(offset);
  270. if (freed) {
  271. return NO_ERROR;
  272. }
  273. return NAME_NOT_FOUND;
  274. }
  275. ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
  276. {
  277. if (size == 0) {
  278. return 0;
  279. }
  280. size = (size + kMemoryAlign-1) / kMemoryAlign;
  281. chunk_t* free_chunk = nullptr;
  282. chunk_t* cur = mList.head();
  283. size_t pagesize = getpagesize();
  284. while (cur) {
  285. int extra = 0;
  286. if (flags & PAGE_ALIGNED)
  287. extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ;
  288. // best fit
  289. if (cur->free && (cur->size >= (size+extra))) {
  290. if ((!free_chunk) || (cur->size < free_chunk->size)) {
  291. free_chunk = cur;
  292. }
  293. if (cur->size == size) {
  294. break;
  295. }
  296. }
  297. cur = cur->next;
  298. }
  299. if (free_chunk) {
  300. const size_t free_size = free_chunk->size;
  301. free_chunk->free = 0;
  302. free_chunk->size = size;
  303. if (free_size > size) {
  304. int extra = 0;
  305. if (flags & PAGE_ALIGNED)
  306. extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ;
  307. if (extra) {
  308. chunk_t* split = new chunk_t(free_chunk->start, extra);
  309. free_chunk->start += extra;
  310. mList.insertBefore(free_chunk, split);
  311. }
  312. ALOGE_IF((flags&PAGE_ALIGNED) &&
  313. ((free_chunk->start*kMemoryAlign)&(pagesize-1)),
  314. "PAGE_ALIGNED requested, but page is not aligned!!!");
  315. const ssize_t tail_free = free_size - (size+extra);
  316. if (tail_free > 0) {
  317. chunk_t* split = new chunk_t(
  318. free_chunk->start + free_chunk->size, tail_free);
  319. mList.insertAfter(free_chunk, split);
  320. }
  321. }
  322. return (free_chunk->start)*kMemoryAlign;
  323. }
  324. return NO_MEMORY;
  325. }
  326. SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
  327. {
  328. start = start / kMemoryAlign;
  329. chunk_t* cur = mList.head();
  330. while (cur) {
  331. if (cur->start == start) {
  332. LOG_FATAL_IF(cur->free,
  333. "block at offset 0x%08lX of size 0x%08lX already freed",
  334. cur->start*kMemoryAlign, cur->size*kMemoryAlign);
  335. // merge freed blocks together
  336. chunk_t* freed = cur;
  337. cur->free = 1;
  338. do {
  339. chunk_t* const p = cur->prev;
  340. chunk_t* const n = cur->next;
  341. if (p && (p->free || !cur->size)) {
  342. freed = p;
  343. p->size += cur->size;
  344. mList.remove(cur);
  345. delete cur;
  346. }
  347. cur = n;
  348. } while (cur && cur->free);
  349. #ifndef NDEBUG
  350. if (!freed->free) {
  351. dump_l("dealloc (!freed->free)");
  352. }
  353. #endif
  354. LOG_FATAL_IF(!freed->free,
  355. "freed block at offset 0x%08lX of size 0x%08lX is not free!",
  356. freed->start * kMemoryAlign, freed->size * kMemoryAlign);
  357. return freed;
  358. }
  359. cur = cur->next;
  360. }
  361. return nullptr;
  362. }
  363. void SimpleBestFitAllocator::dump(const char* what) const
  364. {
  365. Mutex::Autolock _l(mLock);
  366. dump_l(what);
  367. }
  368. void SimpleBestFitAllocator::dump_l(const char* what) const
  369. {
  370. String8 result;
  371. dump_l(result, what);
  372. ALOGD("%s", result.string());
  373. }
  374. void SimpleBestFitAllocator::dump(String8& result,
  375. const char* what) const
  376. {
  377. Mutex::Autolock _l(mLock);
  378. dump_l(result, what);
  379. }
  380. void SimpleBestFitAllocator::dump_l(String8& result,
  381. const char* what) const
  382. {
  383. size_t size = 0;
  384. int32_t i = 0;
  385. chunk_t const* cur = mList.head();
  386. const size_t SIZE = 256;
  387. char buffer[SIZE];
  388. snprintf(buffer, SIZE, " %s (%p, size=%u)\n",
  389. what, this, (unsigned int)mHeapSize);
  390. result.append(buffer);
  391. while (cur) {
  392. const char* errs[] = {"", "| link bogus NP",
  393. "| link bogus PN", "| link bogus NP+PN" };
  394. int np = ((cur->next) && cur->next->prev != cur) ? 1 : 0;
  395. int pn = ((cur->prev) && cur->prev->next != cur) ? 2 : 0;
  396. snprintf(buffer, SIZE, " %3u: %p | 0x%08X | 0x%08X | %s %s\n",
  397. i, cur, int(cur->start*kMemoryAlign),
  398. int(cur->size*kMemoryAlign),
  399. int(cur->free) ? "F" : "A",
  400. errs[np|pn]);
  401. result.append(buffer);
  402. if (!cur->free)
  403. size += cur->size*kMemoryAlign;
  404. i++;
  405. cur = cur->next;
  406. }
  407. snprintf(buffer, SIZE,
  408. " size allocated: %u (%u KB)\n", int(size), int(size/1024));
  409. result.append(buffer);
  410. }
  411. }; // namespace android