CodeCache.cpp revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
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>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/log.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/atomic.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "codeflinger/CodeCache.h"
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnamespace android {
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if defined(__arm__)
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectAssembly::Assembly(size_t size)
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    : mCount(1), mSize(0)
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    mBase = (uint32_t*)malloc(size);
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (mBase) {
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mSize = size;
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectAssembly::~Assembly()
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(mBase);
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid Assembly::incStrong(const void*) const
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    android_atomic_inc(&mCount);
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid Assembly::decStrong(const void*) const
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (android_atomic_dec(&mCount) == 1) {
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        delete this;
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectssize_t Assembly::size() const
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!mBase) return NO_MEMORY;
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return mSize;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectuint32_t* Assembly::base() const
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return mBase;
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectssize_t Assembly::resize(size_t newSize)
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    mBase = (uint32_t*)realloc(mBase, newSize);
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    mSize = newSize;
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return size();
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectCodeCache::CodeCache(size_t size)
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    : mCacheSize(size), mCacheInUse(0)
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_mutex_init(&mLock, 0);
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectCodeCache::~CodeCache()
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_mutex_destroy(&mLock);
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectsp<Assembly> CodeCache::lookup(const AssemblyKeyBase& keyBase) const
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_mutex_lock(&mLock);
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sp<Assembly> r;
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ssize_t index = mCacheData.indexOfKey(key_t(keyBase));
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (index >= 0) {
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const cache_entry_t& e = mCacheData.valueAt(index);
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        e.when = mWhen++;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r = e.entry;
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_mutex_unlock(&mLock);
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return r;
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint CodeCache::cache(  const AssemblyKeyBase& keyBase,
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            const sp<Assembly>& assembly)
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_mutex_lock(&mLock);
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const ssize_t assemblySize = assembly->size();
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (mCacheInUse + assemblySize > mCacheSize) {
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // evict the LRU
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        size_t lru = 0;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        size_t count = mCacheData.size();
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (size_t i=0 ; i<count ; i++) {
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            const cache_entry_t& e = mCacheData.valueAt(i);
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (e.when < mCacheData.valueAt(lru).when) {
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                lru = i;
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const cache_entry_t& e = mCacheData.valueAt(lru);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mCacheInUse -= e.entry->size();
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mCacheData.removeItemsAt(lru);
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ssize_t err = mCacheData.add(key_t(keyBase), cache_entry_t(assembly, mWhen));
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (err >= 0) {
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mCacheInUse += assemblySize;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mWhen++;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // synchronize caches...
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if defined(__arm__)
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const long base = long(assembly->base());
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const long curr = base + long(assembly->size());
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        err = cacheflush(base, curr, 0);
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        LOGE_IF(err, "__ARM_NR_cacheflush error %s\n",
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                strerror(errno));
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pthread_mutex_unlock(&mLock);
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return err;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; // namespace android
152