83c0446f27
- make sure that all binder Bn classes define a ctor and dtor in their respective library. This avoids duplication of the ctor/dtor in libraries where these objects are instantiated. This is also cleaner, should we want these ctor/dtor to do something one day. - same change as above for some Bp classes and various other non-binder classes - moved the definition of CHECK_INTERFACE() in IInterface.h instead of having it everywhere. - improved the CHECK_INTERFACE() macro so it calls a single method in Parcel, instead of inlining its code everywhere - IBinder::getInterfaceDescriptor() now returns a "const String16&" instead of String16, which saves calls to String16 and ~String16 - implemented a cache for BpBinder::getInterfaceDescriptor(), since this does an IPC. HOWEVER, this method never seems to be called. The cache makes BpBinder bigger, so we need to figure out if we need this method at all.
249 lines
6.9 KiB
C++
249 lines
6.9 KiB
C++
/*
|
|
* 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>
|
|
|
|
#if 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
|
|
|
|
#if 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);
|
|
LOGE_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.
|
|
|
|
#if 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);
|
|
LOGE_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)
|
|
: HeapInterface(), MemoryHeapBase()
|
|
{
|
|
char const * const device = pmemHeap->getDevice();
|
|
#if HAVE_ANDROID_OS
|
|
if (device) {
|
|
int fd = open(device, O_RDWR);
|
|
LOGE_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) {
|
|
LOGE("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()
|
|
{
|
|
#if 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);
|
|
LOGE_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()
|
|
{
|
|
#if 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);
|
|
LOGE_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
|