blob: 851664070fe063627df545209b69f6bfef72f674 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/* libs/pixelflinger/codeflinger/CodeCache.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Mark Salyzyn66ce3e02016-09-28 10:07:20 -070018#define LOG_TAG "CodeCache"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080019
20#include <assert.h>
21#include <stdio.h>
22#include <stdlib.h>
Nick Kralevichbeeeee72010-05-06 15:05:52 -070023#include <sys/mman.h>
Mark Salyzyn66ce3e02016-09-28 10:07:20 -070024#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025
Ian Rogers2d137912012-08-17 17:08:48 -070026#include <cutils/ashmem.h>
Mark Salyzyn30f991f2017-01-10 13:19:54 -080027#include <log/log.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028
Mathias Agopian9857d992013-04-01 15:17:55 -070029#include "CodeCache.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030
31namespace android {
32
33// ----------------------------------------------------------------------------
34
Ashok Bhat658f89d2013-02-28 18:32:03 +000035#if defined(__arm__) || defined(__aarch64__)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080036#include <unistd.h>
37#include <errno.h>
38#endif
39
Paul Lind2bc2b792012-02-01 10:54:19 -080040#if defined(__mips__)
41#include <asm/cachectl.h>
42#include <errno.h>
43#endif
44
45// ----------------------------------------------------------------------------
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046// ----------------------------------------------------------------------------
47
Ian Rogers2d137912012-08-17 17:08:48 -070048// A dlmalloc mspace is used to manage the code cache over a mmaped region.
49#define HAVE_MMAP 0
50#define HAVE_MREMAP 0
51#define HAVE_MORECORE 0
52#define MALLOC_ALIGNMENT 16
53#define MSPACES 1
54#define NO_MALLINFO 1
55#define ONLY_MSPACES 1
56// Custom heap error handling.
57#define PROCEED_ON_ERROR 0
58static void heap_error(const char* msg, const char* function, void* p);
59#define CORRUPTION_ERROR_ACTION(m) \
60 heap_error("HEAP MEMORY CORRUPTION", __FUNCTION__, NULL)
61#define USAGE_ERROR_ACTION(m,p) \
62 heap_error("ARGUMENT IS INVALID HEAP ADDRESS", __FUNCTION__, p)
63
Josh Gao70bde212016-01-22 11:04:35 -080064#include "../../../../external/dlmalloc/malloc.c"
Ian Rogers2d137912012-08-17 17:08:48 -070065
66static void heap_error(const char* msg, const char* function, void* p) {
67 ALOG(LOG_FATAL, LOG_TAG, "@@@ ABORTING: CODE FLINGER: %s IN %s addr=%p",
68 msg, function, p);
69 /* So that we can get a memory dump around p */
70 *((int **) 0xdeadbaad) = (int *) p;
71}
72
73// ----------------------------------------------------------------------------
74
75static void* gExecutableStore = NULL;
76static mspace gMspace = NULL;
77const size_t kMaxCodeCacheCapacity = 1024 * 1024;
78
79static mspace getMspace()
80{
81 if (gExecutableStore == NULL) {
82 int fd = ashmem_create_region("CodeFlinger code cache",
83 kMaxCodeCacheCapacity);
84 LOG_ALWAYS_FATAL_IF(fd < 0,
85 "Creating code cache, ashmem_create_region "
86 "failed with error '%s'", strerror(errno));
87 gExecutableStore = mmap(NULL, kMaxCodeCacheCapacity,
88 PROT_READ | PROT_WRITE | PROT_EXEC,
89 MAP_PRIVATE, fd, 0);
Hurri Lu473a7292014-05-22 11:38:12 +080090 LOG_ALWAYS_FATAL_IF(gExecutableStore == MAP_FAILED,
Ian Rogers2d137912012-08-17 17:08:48 -070091 "Creating code cache, mmap failed with error "
92 "'%s'", strerror(errno));
93 close(fd);
94 gMspace = create_mspace_with_base(gExecutableStore, kMaxCodeCacheCapacity,
95 /*locked=*/ false);
96 mspace_set_footprint_limit(gMspace, kMaxCodeCacheCapacity);
97 }
98 return gMspace;
99}
100
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800101Assembly::Assembly(size_t size)
Hans Boehme74dec42016-08-10 18:44:14 -0700102 : mCount(0), mSize(0)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800103{
Nick Kralevichbeeeee72010-05-06 15:05:52 -0700104 mBase = (uint32_t*)mspace_malloc(getMspace(), size);
Ian Rogers2d137912012-08-17 17:08:48 -0700105 LOG_ALWAYS_FATAL_IF(mBase == NULL,
106 "Failed to create Assembly of size %zd in executable "
107 "store of size %zd", size, kMaxCodeCacheCapacity);
Nick Kralevichbeeeee72010-05-06 15:05:52 -0700108 mSize = size;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109}
110
111Assembly::~Assembly()
112{
Nick Kralevichbeeeee72010-05-06 15:05:52 -0700113 mspace_free(getMspace(), mBase);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800114}
115
116void Assembly::incStrong(const void*) const
117{
Hans Boehme74dec42016-08-10 18:44:14 -0700118 mCount.fetch_add(1, std::memory_order_relaxed);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800119}
120
121void Assembly::decStrong(const void*) const
122{
Hans Boehme74dec42016-08-10 18:44:14 -0700123 if (mCount.fetch_sub(1, std::memory_order_acq_rel) == 1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800124 delete this;
125 }
126}
127
128ssize_t Assembly::size() const
129{
130 if (!mBase) return NO_MEMORY;
131 return mSize;
132}
133
134uint32_t* Assembly::base() const
135{
136 return mBase;
137}
138
139ssize_t Assembly::resize(size_t newSize)
140{
Nick Kralevichbeeeee72010-05-06 15:05:52 -0700141 mBase = (uint32_t*)mspace_realloc(getMspace(), mBase, newSize);
Ian Rogers2d137912012-08-17 17:08:48 -0700142 LOG_ALWAYS_FATAL_IF(mBase == NULL,
143 "Failed to resize Assembly to %zd in code cache "
144 "of size %zd", newSize, kMaxCodeCacheCapacity);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800145 mSize = newSize;
146 return size();
147}
148
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800149// ----------------------------------------------------------------------------
150
151CodeCache::CodeCache(size_t size)
152 : mCacheSize(size), mCacheInUse(0)
153{
154 pthread_mutex_init(&mLock, 0);
155}
156
157CodeCache::~CodeCache()
158{
159 pthread_mutex_destroy(&mLock);
160}
161
162sp<Assembly> CodeCache::lookup(const AssemblyKeyBase& keyBase) const
163{
164 pthread_mutex_lock(&mLock);
165 sp<Assembly> r;
166 ssize_t index = mCacheData.indexOfKey(key_t(keyBase));
167 if (index >= 0) {
168 const cache_entry_t& e = mCacheData.valueAt(index);
169 e.when = mWhen++;
170 r = e.entry;
171 }
172 pthread_mutex_unlock(&mLock);
173 return r;
174}
175
176int CodeCache::cache( const AssemblyKeyBase& keyBase,
177 const sp<Assembly>& assembly)
178{
179 pthread_mutex_lock(&mLock);
180
181 const ssize_t assemblySize = assembly->size();
182 while (mCacheInUse + assemblySize > mCacheSize) {
183 // evict the LRU
184 size_t lru = 0;
185 size_t count = mCacheData.size();
186 for (size_t i=0 ; i<count ; i++) {
187 const cache_entry_t& e = mCacheData.valueAt(i);
188 if (e.when < mCacheData.valueAt(lru).when) {
189 lru = i;
190 }
191 }
192 const cache_entry_t& e = mCacheData.valueAt(lru);
193 mCacheInUse -= e.entry->size();
194 mCacheData.removeItemsAt(lru);
195 }
196
197 ssize_t err = mCacheData.add(key_t(keyBase), cache_entry_t(assembly, mWhen));
198 if (err >= 0) {
199 mCacheInUse += assemblySize;
200 mWhen++;
201 // synchronize caches...
Dan Albert949aa232014-09-08 19:09:41 -0700202 char* base = reinterpret_cast<char*>(assembly->base());
203 char* curr = reinterpret_cast<char*>(base + assembly->size());
Ashok Bhat410ae2f2014-06-19 11:03:32 +0100204 __builtin___clear_cache(base, curr);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800205 }
206
207 pthread_mutex_unlock(&mLock);
208 return err;
209}
210
211// ----------------------------------------------------------------------------
212
213}; // namespace android