beeeee705b
Instead of allocating memory from the (non executable) heap, allocate memory using mspace and ensure that we use mprotect to mark it as PROT_EXEC. This allows pixelflinger to continue to work even when NX protections are enabled. Testing: Using the ApiDemos market app, verify that Apidemos -> Graphics -> OpenGL ES -> GLSurfaceView works when "adb shell setprop debug.egl.hw 0" is set. Change-Id: Ib569cd2543c6fa25688ee76325a712bc2347450b
137 lines
3.9 KiB
C++
137 lines
3.9 KiB
C++
/* libs/pixelflinger/codeflinger/CodeCache.h
|
|
**
|
|
** Copyright 2006, The Android Open Source Project
|
|
**
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
** you may not use this file except in compliance with the License.
|
|
** You may obtain a copy of the License at
|
|
**
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
**
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
** See the License for the specific language governing permissions and
|
|
** limitations under the License.
|
|
*/
|
|
|
|
|
|
#ifndef ANDROID_CODECACHE_H
|
|
#define ANDROID_CODECACHE_H
|
|
|
|
#include <stdint.h>
|
|
#include <pthread.h>
|
|
#include <sys/types.h>
|
|
#include <cutils/mspace.h>
|
|
|
|
#include "tinyutils/KeyedVector.h"
|
|
#include "tinyutils/smartpointer.h"
|
|
|
|
namespace android {
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class AssemblyKeyBase {
|
|
public:
|
|
virtual ~AssemblyKeyBase() { }
|
|
virtual int compare_type(const AssemblyKeyBase& key) const = 0;
|
|
};
|
|
|
|
template <typename T>
|
|
class AssemblyKey : public AssemblyKeyBase
|
|
{
|
|
public:
|
|
AssemblyKey(const T& rhs) : mKey(rhs) { }
|
|
virtual int compare_type(const AssemblyKeyBase& key) const {
|
|
const T& rhs = static_cast<const AssemblyKey&>(key).mKey;
|
|
return android::compare_type(mKey, rhs);
|
|
}
|
|
private:
|
|
T mKey;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class Assembly
|
|
{
|
|
public:
|
|
Assembly(size_t size);
|
|
virtual ~Assembly();
|
|
|
|
ssize_t size() const;
|
|
uint32_t* base() const;
|
|
ssize_t resize(size_t size);
|
|
|
|
// protocol for sp<>
|
|
void incStrong(const void* id) const;
|
|
void decStrong(const void* id) const;
|
|
typedef void weakref_type;
|
|
|
|
private:
|
|
static mspace getMspace();
|
|
void ensureMbaseExecutable();
|
|
|
|
mutable int32_t mCount;
|
|
uint32_t* mBase;
|
|
size_t mSize;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class CodeCache
|
|
{
|
|
public:
|
|
// pretty simple cache API...
|
|
CodeCache(size_t size);
|
|
~CodeCache();
|
|
|
|
sp<Assembly> lookup(const AssemblyKeyBase& key) const;
|
|
|
|
int cache( const AssemblyKeyBase& key,
|
|
const sp<Assembly>& assembly);
|
|
|
|
private:
|
|
// nothing to see here...
|
|
struct cache_entry_t {
|
|
inline cache_entry_t() { }
|
|
inline cache_entry_t(const sp<Assembly>& a, int64_t w)
|
|
: entry(a), when(w) { }
|
|
sp<Assembly> entry;
|
|
mutable int64_t when;
|
|
};
|
|
|
|
class key_t {
|
|
friend int compare_type(
|
|
const key_value_pair_t<key_t, cache_entry_t>&,
|
|
const key_value_pair_t<key_t, cache_entry_t>&);
|
|
const AssemblyKeyBase* mKey;
|
|
public:
|
|
key_t() { };
|
|
key_t(const AssemblyKeyBase& k) : mKey(&k) { }
|
|
};
|
|
|
|
mutable pthread_mutex_t mLock;
|
|
mutable int64_t mWhen;
|
|
size_t mCacheSize;
|
|
size_t mCacheInUse;
|
|
KeyedVector<key_t, cache_entry_t> mCacheData;
|
|
|
|
friend int compare_type(
|
|
const key_value_pair_t<key_t, cache_entry_t>&,
|
|
const key_value_pair_t<key_t, cache_entry_t>&);
|
|
};
|
|
|
|
// KeyedVector uses compare_type(), which is more efficient, than
|
|
// just using operator < ()
|
|
inline int compare_type(
|
|
const key_value_pair_t<CodeCache::key_t, CodeCache::cache_entry_t>& lhs,
|
|
const key_value_pair_t<CodeCache::key_t, CodeCache::cache_entry_t>& rhs)
|
|
{
|
|
return lhs.key.mKey->compare_type(*(rhs.key.mKey));
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
}; // namespace android
|
|
|
|
#endif //ANDROID_CODECACHE_H
|