CodeCache.cpp revision beeeee705bcf16d705748713ea40dca3486cc7b7
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 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------- 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectAssembly::Assembly(size_t size) 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project : mCount(1), mSize(0) 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 44beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mBase = (uint32_t*)mspace_malloc(getMspace(), size); 45beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mSize = size; 46beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich ensureMbaseExecutable(); 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectAssembly::~Assembly() 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 51beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mspace_free(getMspace(), mBase); 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid Assembly::incStrong(const void*) const 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project android_atomic_inc(&mCount); 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid Assembly::decStrong(const void*) const 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (android_atomic_dec(&mCount) == 1) { 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project delete this; 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectssize_t Assembly::size() const 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!mBase) return NO_MEMORY; 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return mSize; 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectuint32_t* Assembly::base() const 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return mBase; 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectssize_t Assembly::resize(size_t newSize) 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 79beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mBase = (uint32_t*)mspace_realloc(getMspace(), mBase, newSize); 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mSize = newSize; 81beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich ensureMbaseExecutable(); 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return size(); 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 85beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevichmspace Assembly::getMspace() 86beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich{ 87beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich static mspace msp = create_contiguous_mspace(2 * 1024, 1024 * 1024, /*locked=*/ false); 88beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich return msp; 89beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich} 90beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich 91beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevichvoid Assembly::ensureMbaseExecutable() 92beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich{ 93beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich long pagesize = sysconf(_SC_PAGESIZE); 94beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich long pagemask = ~(pagesize - 1); // assumes pagesize is a power of 2 95beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich 96beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich uint32_t* pageStart = (uint32_t*) (((uintptr_t) mBase) & pagemask); 97beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich size_t adjustedLength = mBase - pageStart + mSize; 98beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich 99beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich if (mBase && mprotect(pageStart, adjustedLength, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { 100beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mspace_free(getMspace(), mBase); 101beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich mBase = NULL; 102beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich } 103beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich} 104beeeee705bcf16d705748713ea40dca3486cc7b7Nick Kralevich 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------- 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectCodeCache::CodeCache(size_t size) 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project : mCacheSize(size), mCacheInUse(0) 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_init(&mLock, 0); 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectCodeCache::~CodeCache() 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_destroy(&mLock); 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectsp<Assembly> CodeCache::lookup(const AssemblyKeyBase& keyBase) const 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_lock(&mLock); 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sp<Assembly> r; 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t index = mCacheData.indexOfKey(key_t(keyBase)); 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (index >= 0) { 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const cache_entry_t& e = mCacheData.valueAt(index); 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project e.when = mWhen++; 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = e.entry; 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_unlock(&mLock); 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return r; 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint CodeCache::cache( const AssemblyKeyBase& keyBase, 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const sp<Assembly>& assembly) 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_lock(&mLock); 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const ssize_t assemblySize = assembly->size(); 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (mCacheInUse + assemblySize > mCacheSize) { 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // evict the LRU 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project size_t lru = 0; 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project size_t count = mCacheData.size(); 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (size_t i=0 ; i<count ; i++) { 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const cache_entry_t& e = mCacheData.valueAt(i); 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (e.when < mCacheData.valueAt(lru).when) { 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project lru = i; 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const cache_entry_t& e = mCacheData.valueAt(lru); 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mCacheInUse -= e.entry->size(); 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mCacheData.removeItemsAt(lru); 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t err = mCacheData.add(key_t(keyBase), cache_entry_t(assembly, mWhen)); 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (err >= 0) { 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mCacheInUse += assemblySize; 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project mWhen++; 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // synchronize caches... 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if defined(__arm__) 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const long base = long(assembly->base()); 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const long curr = base + long(assembly->size()); 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project err = cacheflush(base, curr, 0); 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOGE_IF(err, "__ARM_NR_cacheflush error %s\n", 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strerror(errno)); 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_unlock(&mLock); 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return err; 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------- 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; // namespace android 174