CodeCache.cpp revision 2bc2b792782b304b15d8c48b54916a9b3fa3a7ac
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* libs/pixelflinger/codeflinger/CodeCache.cpp 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2006, The Android Open Source Project 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** you may not use this file except in compliance with the License. 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** You may obtain a copy of the License at 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** See the License for the specific language governing permissions and 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** limitations under the License. 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/ 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <assert.h> 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 22beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich#include <unistd.h> 23beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich#include <sys/mman.h> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/log.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/atomic.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "codeflinger/CodeCache.h" 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnamespace android { 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------- 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if defined(__arm__) 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 392bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if defined(__mips__) 402bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include <asm/cachectl.h> 412bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#include <errno.h> 422bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#endif 432bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind 442bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind// ---------------------------------------------------------------------------- 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------- 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectAssembly::Assembly(size_t size) 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project : mCount(1), mSize(0) 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 50beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mBase = (uint32_t*)mspace_malloc(getMspace(), size); 51beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mSize = size; 52beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich ensureMbaseExecutable(); 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectAssembly::~Assembly() 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 57beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mspace_free(getMspace(), mBase); 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid Assembly::incStrong(const void*) const 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project android_atomic_inc(&mCount); 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid Assembly::decStrong(const void*) const 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (android_atomic_dec(&mCount) == 1) { 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project delete this; 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectssize_t Assembly::size() const 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!mBase) return NO_MEMORY; 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return mSize; 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectuint32_t* Assembly::base() const 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return mBase; 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectssize_t Assembly::resize(size_t newSize) 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 85beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mBase = (uint32_t*)mspace_realloc(getMspace(), mBase, newSize); 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mSize = newSize; 87beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich ensureMbaseExecutable(); 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return size(); 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 91beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevichmspace Assembly::getMspace() 92beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich{ 93beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich static mspace msp = create_contiguous_mspace(2 * 1024, 1024 * 1024, /*locked=*/ false); 94beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich return msp; 95beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich} 96beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich 97beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevichvoid Assembly::ensureMbaseExecutable() 98beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich{ 99beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich long pagesize = sysconf(_SC_PAGESIZE); 100beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich long pagemask = ~(pagesize - 1); // assumes pagesize is a power of 2 101beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich 102beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich uint32_t* pageStart = (uint32_t*) (((uintptr_t) mBase) & pagemask); 1038e0e372a388434a0553810e2b958e59a26a6bd96Jean-Baptiste Queru size_t adjustedLength = (mBase - pageStart) * sizeof(uint32_t) + mSize; 104beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich 105beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich if (mBase && mprotect(pageStart, adjustedLength, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { 106beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mspace_free(getMspace(), mBase); 107beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mBase = NULL; 108beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich } 109beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich} 110beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------- 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectCodeCache::CodeCache(size_t size) 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project : mCacheSize(size), mCacheInUse(0) 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_init(&mLock, 0); 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectCodeCache::~CodeCache() 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_destroy(&mLock); 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectsp<Assembly> CodeCache::lookup(const AssemblyKeyBase& keyBase) const 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_lock(&mLock); 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sp<Assembly> r; 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t index = mCacheData.indexOfKey(key_t(keyBase)); 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (index >= 0) { 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const cache_entry_t& e = mCacheData.valueAt(index); 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project e.when = mWhen++; 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = e.entry; 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_unlock(&mLock); 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return r; 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint CodeCache::cache( const AssemblyKeyBase& keyBase, 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const sp<Assembly>& assembly) 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_lock(&mLock); 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const ssize_t assemblySize = assembly->size(); 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (mCacheInUse + assemblySize > mCacheSize) { 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // evict the LRU 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project size_t lru = 0; 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project size_t count = mCacheData.size(); 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (size_t i=0 ; i<count ; i++) { 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const cache_entry_t& e = mCacheData.valueAt(i); 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (e.when < mCacheData.valueAt(lru).when) { 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project lru = i; 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const cache_entry_t& e = mCacheData.valueAt(lru); 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mCacheInUse -= e.entry->size(); 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mCacheData.removeItemsAt(lru); 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t err = mCacheData.add(key_t(keyBase), cache_entry_t(assembly, mWhen)); 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (err >= 0) { 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mCacheInUse += assemblySize; 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mWhen++; 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // synchronize caches... 1642bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind#if defined(__arm__) || defined(__mips__) 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const long base = long(assembly->base()); 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const long curr = base + long(assembly->size()); 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = cacheflush(base, curr, 0); 1682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind ALOGE_IF(err, "cacheflush error %s\n", 1692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind strerror(errno)); 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_unlock(&mLock); 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return err; 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------- 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; // namespace android 180