-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This reverts commit 7a75248 and makes MemoryHeapPmem conditioned to BOARD_NEEDS_MEMORYHEAPPMEM Change-Id: I2f38340984ba87d6970d17ec944e3faded4132c8
- Loading branch information
Showing
3 changed files
with
332 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* Copyright (C) 2008 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_MEMORY_HEAP_PMEM_H | ||
#define ANDROID_MEMORY_HEAP_PMEM_H | ||
|
||
#include <stdlib.h> | ||
#include <stdint.h> | ||
|
||
#include <binder/MemoryHeapBase.h> | ||
#include <binder/IMemory.h> | ||
#include <utils/SortedVector.h> | ||
#include <utils/threads.h> | ||
|
||
namespace android { | ||
|
||
class MemoryHeapBase; | ||
|
||
// --------------------------------------------------------------------------- | ||
|
||
class MemoryHeapPmem : public MemoryHeapBase | ||
{ | ||
public: | ||
class MemoryPmem : public BnMemory { | ||
public: | ||
MemoryPmem(const sp<MemoryHeapPmem>& heap); | ||
~MemoryPmem(); | ||
protected: | ||
const sp<MemoryHeapPmem>& getHeap() const { return mClientHeap; } | ||
private: | ||
friend class MemoryHeapPmem; | ||
virtual void revoke() = 0; | ||
sp<MemoryHeapPmem> mClientHeap; | ||
}; | ||
|
||
MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap, uint32_t flags = 0); | ||
~MemoryHeapPmem(); | ||
|
||
/* HeapInterface additions */ | ||
virtual sp<IMemory> mapMemory(size_t offset, size_t size); | ||
|
||
/* make the whole heap visible (you know who you are) */ | ||
virtual status_t slap(); | ||
|
||
/* hide (revoke) the whole heap (the client will see the garbage page) */ | ||
virtual status_t unslap(); | ||
|
||
/* revoke all allocations made by this heap */ | ||
virtual void revoke(); | ||
|
||
private: | ||
/* use this to create your own IMemory for mapMemory */ | ||
virtual sp<MemoryPmem> createMemory(size_t offset, size_t size); | ||
void remove(const wp<MemoryPmem>& memory); | ||
|
||
private: | ||
sp<MemoryHeapBase> mParentHeap; | ||
mutable Mutex mLock; | ||
SortedVector< wp<MemoryPmem> > mAllocations; | ||
}; | ||
|
||
|
||
// --------------------------------------------------------------------------- | ||
}; // namespace android | ||
|
||
#endif // ANDROID_MEMORY_HEAP_PMEM_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
/* | ||
* Copyright (C) 2008 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. | ||
*/ | ||
|
||
#define LOG_TAG "MemoryHeapPmem" | ||
|
||
#include <stdlib.h> | ||
#include <stdint.h> | ||
#include <unistd.h> | ||
#include <fcntl.h> | ||
#include <errno.h> | ||
#include <sys/types.h> | ||
#include <sys/stat.h> | ||
#include <sys/ioctl.h> | ||
|
||
#include <cutils/log.h> | ||
|
||
#include <binder/MemoryHeapPmem.h> | ||
#include <binder/MemoryHeapBase.h> | ||
|
||
#ifdef HAVE_ANDROID_OS | ||
#include <linux/android_pmem.h> | ||
#endif | ||
|
||
namespace android { | ||
|
||
// --------------------------------------------------------------------------- | ||
|
||
MemoryHeapPmem::MemoryPmem::MemoryPmem(const sp<MemoryHeapPmem>& heap) | ||
: BnMemory(), mClientHeap(heap) | ||
{ | ||
} | ||
|
||
MemoryHeapPmem::MemoryPmem::~MemoryPmem() { | ||
if (mClientHeap != NULL) { | ||
mClientHeap->remove(this); | ||
} | ||
} | ||
|
||
// --------------------------------------------------------------------------- | ||
|
||
class SubRegionMemory : public MemoryHeapPmem::MemoryPmem { | ||
public: | ||
SubRegionMemory(const sp<MemoryHeapPmem>& heap, ssize_t offset, size_t size); | ||
virtual ~SubRegionMemory(); | ||
virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const; | ||
private: | ||
friend class MemoryHeapPmem; | ||
void revoke(); | ||
size_t mSize; | ||
ssize_t mOffset; | ||
}; | ||
|
||
SubRegionMemory::SubRegionMemory(const sp<MemoryHeapPmem>& heap, | ||
ssize_t offset, size_t size) | ||
: MemoryHeapPmem::MemoryPmem(heap), mSize(size), mOffset(offset) | ||
{ | ||
#ifndef NDEBUG | ||
void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + offset); | ||
memset(start_ptr, 0xda, size); | ||
#endif | ||
|
||
#ifdef HAVE_ANDROID_OS | ||
if (size > 0) { | ||
const size_t pagesize = getpagesize(); | ||
size = (size + pagesize-1) & ~(pagesize-1); | ||
int our_fd = heap->heapID(); | ||
struct pmem_region sub = { offset, size }; | ||
int err = ioctl(our_fd, PMEM_MAP, &sub); | ||
ALOGE_IF(err<0, "PMEM_MAP failed (%s), " | ||
"mFD=%d, sub.offset=%lu, sub.size=%lu", | ||
strerror(errno), our_fd, sub.offset, sub.len); | ||
} | ||
#endif | ||
} | ||
|
||
sp<IMemoryHeap> SubRegionMemory::getMemory(ssize_t* offset, size_t* size) const | ||
{ | ||
if (offset) *offset = mOffset; | ||
if (size) *size = mSize; | ||
return getHeap(); | ||
} | ||
|
||
SubRegionMemory::~SubRegionMemory() | ||
{ | ||
revoke(); | ||
} | ||
|
||
|
||
void SubRegionMemory::revoke() | ||
{ | ||
// NOTE: revoke() doesn't need to be protected by a lock because it | ||
// can only be called from MemoryHeapPmem::revoke(), which means | ||
// that we can't be in ~SubRegionMemory(), or in ~SubRegionMemory(), | ||
// which means MemoryHeapPmem::revoke() wouldn't have been able to | ||
// promote() it. | ||
|
||
#ifdef HAVE_ANDROID_OS | ||
if (mSize != 0) { | ||
const sp<MemoryHeapPmem>& heap(getHeap()); | ||
int our_fd = heap->heapID(); | ||
struct pmem_region sub; | ||
sub.offset = mOffset; | ||
sub.len = mSize; | ||
int err = ioctl(our_fd, PMEM_UNMAP, &sub); | ||
ALOGE_IF(err<0, "PMEM_UNMAP failed (%s), " | ||
"mFD=%d, sub.offset=%lu, sub.size=%lu", | ||
strerror(errno), our_fd, sub.offset, sub.len); | ||
mSize = 0; | ||
} | ||
#endif | ||
} | ||
|
||
// --------------------------------------------------------------------------- | ||
|
||
MemoryHeapPmem::MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap, | ||
uint32_t flags) | ||
: MemoryHeapBase() | ||
{ | ||
char const * const device = pmemHeap->getDevice(); | ||
#ifdef HAVE_ANDROID_OS | ||
if (device) { | ||
int fd = open(device, O_RDWR | (flags & NO_CACHING ? O_SYNC : 0)); | ||
ALOGE_IF(fd<0, "couldn't open %s (%s)", device, strerror(errno)); | ||
if (fd >= 0) { | ||
int err = ioctl(fd, PMEM_CONNECT, pmemHeap->heapID()); | ||
if (err < 0) { | ||
ALOGE("PMEM_CONNECT failed (%s), mFD=%d, sub-fd=%d", | ||
strerror(errno), fd, pmemHeap->heapID()); | ||
close(fd); | ||
} else { | ||
// everything went well... | ||
mParentHeap = pmemHeap; | ||
MemoryHeapBase::init(fd, | ||
pmemHeap->getBase(), | ||
pmemHeap->getSize(), | ||
pmemHeap->getFlags() | flags, | ||
device); | ||
} | ||
} | ||
} | ||
#else | ||
mParentHeap = pmemHeap; | ||
MemoryHeapBase::init( | ||
dup(pmemHeap->heapID()), | ||
pmemHeap->getBase(), | ||
pmemHeap->getSize(), | ||
pmemHeap->getFlags() | flags, | ||
device); | ||
#endif | ||
} | ||
|
||
MemoryHeapPmem::~MemoryHeapPmem() | ||
{ | ||
} | ||
|
||
sp<IMemory> MemoryHeapPmem::mapMemory(size_t offset, size_t size) | ||
{ | ||
sp<MemoryPmem> memory = createMemory(offset, size); | ||
if (memory != 0) { | ||
Mutex::Autolock _l(mLock); | ||
mAllocations.add(memory); | ||
} | ||
return memory; | ||
} | ||
|
||
sp<MemoryHeapPmem::MemoryPmem> MemoryHeapPmem::createMemory( | ||
size_t offset, size_t size) | ||
{ | ||
sp<SubRegionMemory> memory; | ||
if (heapID() > 0) | ||
memory = new SubRegionMemory(this, offset, size); | ||
return memory; | ||
} | ||
|
||
status_t MemoryHeapPmem::slap() | ||
{ | ||
#ifdef HAVE_ANDROID_OS | ||
size_t size = getSize(); | ||
const size_t pagesize = getpagesize(); | ||
size = (size + pagesize-1) & ~(pagesize-1); | ||
int our_fd = getHeapID(); | ||
struct pmem_region sub = { 0, size }; | ||
int err = ioctl(our_fd, PMEM_MAP, &sub); | ||
ALOGE_IF(err<0, "PMEM_MAP failed (%s), " | ||
"mFD=%d, sub.offset=%lu, sub.size=%lu", | ||
strerror(errno), our_fd, sub.offset, sub.len); | ||
return -errno; | ||
#else | ||
return NO_ERROR; | ||
#endif | ||
} | ||
|
||
status_t MemoryHeapPmem::unslap() | ||
{ | ||
#ifdef HAVE_ANDROID_OS | ||
size_t size = getSize(); | ||
const size_t pagesize = getpagesize(); | ||
size = (size + pagesize-1) & ~(pagesize-1); | ||
int our_fd = getHeapID(); | ||
struct pmem_region sub = { 0, size }; | ||
int err = ioctl(our_fd, PMEM_UNMAP, &sub); | ||
ALOGE_IF(err<0, "PMEM_UNMAP failed (%s), " | ||
"mFD=%d, sub.offset=%lu, sub.size=%lu", | ||
strerror(errno), our_fd, sub.offset, sub.len); | ||
return -errno; | ||
#else | ||
return NO_ERROR; | ||
#endif | ||
} | ||
|
||
void MemoryHeapPmem::revoke() | ||
{ | ||
SortedVector< wp<MemoryPmem> > allocations; | ||
|
||
{ // scope for lock | ||
Mutex::Autolock _l(mLock); | ||
allocations = mAllocations; | ||
} | ||
|
||
ssize_t count = allocations.size(); | ||
for (ssize_t i=0 ; i<count ; i++) { | ||
sp<MemoryPmem> memory(allocations[i].promote()); | ||
if (memory != 0) | ||
memory->revoke(); | ||
} | ||
} | ||
|
||
void MemoryHeapPmem::remove(const wp<MemoryPmem>& memory) | ||
{ | ||
Mutex::Autolock _l(mLock); | ||
mAllocations.remove(memory); | ||
} | ||
|
||
// --------------------------------------------------------------------------- | ||
}; // namespace android |