diff options
author | Steve Kondik <shade@chemlab.org> | 2010-08-08 00:29:51 -0400 |
---|---|---|
committer | Steve Kondik <shade@chemlab.org> | 2010-08-08 01:20:50 -0400 |
commit | 30b3f7a1f05a24baf1d798231813adc560c308b8 (patch) | |
tree | 64b8f181526a70bd7e78816afd3d6f8e6c951fe2 /libs | |
parent | 64d00b642a36198e322140dea67d3203449ae579 (diff) | |
download | frameworks_base-30b3f7a1f05a24baf1d798231813adc560c308b8.zip frameworks_base-30b3f7a1f05a24baf1d798231813adc560c308b8.tar.gz frameworks_base-30b3f7a1f05a24baf1d798231813adc560c308b8.tar.bz2 |
HACK: Allow use of Eclair MemoryDealer for compatibility.
Diffstat (limited to 'libs')
-rw-r--r-- | libs/audioflinger/Android.mk | 4 | ||||
-rw-r--r-- | libs/audioflinger/AudioFlinger.cpp | 4 | ||||
-rw-r--r-- | libs/audioflinger/AudioFlinger.h | 4 | ||||
-rw-r--r-- | libs/binder/Android.mk | 8 | ||||
-rw-r--r-- | libs/binder/MemoryDealerEclair.cpp | 421 | ||||
-rw-r--r-- | libs/binder/MemoryHeapPmem.cpp | 4 |
6 files changed, 444 insertions, 1 deletions
diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk index 3082813..bd64135 100644 --- a/libs/audioflinger/Android.mk +++ b/libs/audioflinger/Android.mk @@ -105,6 +105,10 @@ endif LOCAL_MODULE:= libaudioflinger +ifeq ($(BOARD_USES_ECLAIR_LIBCAMERA),true) + LOCAL_CFLAGS += -DUSE_ECLAIR_MEMORYDEALER +endif + ifeq ($(BOARD_HAVE_BLUETOOTH),true) LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP LOCAL_SHARED_LIBRARIES += liba2dp diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index a2fbca1..890692d 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -3069,7 +3069,11 @@ void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue() AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid) : RefBase(), mAudioFlinger(audioFlinger), +#ifdef USE_ECLAIR_MEMORYDEALER + mMemoryDealer(new MemoryDealer(1024*1024)), +#else mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")), +#endif mPid(pid) { // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index 8f99cf8..d310477 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -31,7 +31,11 @@ #include <utils/Atomic.h> #include <utils/Errors.h> #include <utils/threads.h> +#ifdef USE_ECLAIR_MEMORYDEALER +#include <binder/MemoryDealerEclair.h> +#else #include <binder/MemoryDealer.h> +#endif #include <utils/SortedVector.h> #include <utils/Vector.h> diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk index 13dc500..dc43f5f 100644 --- a/libs/binder/Android.mk +++ b/libs/binder/Android.mk @@ -21,7 +21,6 @@ sources := \ IPCThreadState.cpp \ IPermissionController.cpp \ IServiceManager.cpp \ - MemoryDealer.cpp \ MemoryBase.cpp \ MemoryHeapBase.cpp \ MemoryHeapPmem.cpp \ @@ -30,6 +29,13 @@ sources := \ ProcessState.cpp \ Static.cpp +ifeq ($(strip $(BOARD_USES_ECLAIR_LIBCAMERA)), true) + LOCAL_CFLAGS += -DUSE_ECLAIR_MEMORYDEALER + sources += MemoryDealerEclair.cpp +else + sources += MemoryDealer.cpp +endif + LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) diff --git a/libs/binder/MemoryDealerEclair.cpp b/libs/binder/MemoryDealerEclair.cpp new file mode 100644 index 0000000..1b192d6 --- /dev/null +++ b/libs/binder/MemoryDealerEclair.cpp @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2007 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 "MemoryDealer" + +#include <binder/MemoryDealerEclair.h> + +#include <utils/Log.h> +#include <binder/IPCThreadState.h> +#include <utils/SortedVector.h> +#include <utils/String8.h> +#include <binder/MemoryBase.h> + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/file.h> + +namespace android { +// ---------------------------------------------------------------------------- + +HeapInterface::HeapInterface() { } +HeapInterface::~HeapInterface() { } + +// ---------------------------------------------------------------------------- + +AllocatorInterface::AllocatorInterface() { } +AllocatorInterface::~AllocatorInterface() { } + +// ---------------------------------------------------------------------------- + +class SimpleMemory : public MemoryBase { +public: + SimpleMemory(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size); + virtual ~SimpleMemory(); +}; + + +// ---------------------------------------------------------------------------- + +MemoryDealer::Allocation::Allocation( + const sp<MemoryDealer>& dealer, ssize_t offset, size_t size, + const sp<IMemory>& memory) + : mDealer(dealer), mOffset(offset), mSize(size), mMemory(memory) +{ +} + +MemoryDealer::Allocation::~Allocation() +{ + if (mSize) { + /* NOTE: it's VERY important to not free allocations of size 0 because + * they're special as they don't have any record in the allocator + * and could alias some real allocation (their offset is zero). */ + mDealer->deallocate(mOffset); + } +} + +sp<IMemoryHeap> MemoryDealer::Allocation::getMemory( + ssize_t* offset, size_t* size) const +{ + return mMemory->getMemory(offset, size); +} + +// ---------------------------------------------------------------------------- + +MemoryDealer::MemoryDealer(size_t size, uint32_t flags, const char* name) + : mHeap(new SharedHeap(size, flags, name)), + mAllocator(new SimpleBestFitAllocator(size)) +{ +} + +MemoryDealer::MemoryDealer(const sp<HeapInterface>& heap) + : mHeap(heap), + mAllocator(new SimpleBestFitAllocator(heap->virtualSize())) +{ +} + +MemoryDealer::MemoryDealer( const sp<HeapInterface>& heap, + const sp<AllocatorInterface>& allocator) + : mHeap(heap), mAllocator(allocator) +{ +} + +MemoryDealer::~MemoryDealer() +{ +} + +sp<IMemory> MemoryDealer::allocate(size_t size, uint32_t flags) +{ + sp<IMemory> memory; + const ssize_t offset = allocator()->allocate(size, flags); + if (offset >= 0) { + sp<IMemory> new_memory = heap()->mapMemory(offset, size); + if (new_memory != 0) { + memory = new Allocation(this, offset, size, new_memory); + } else { + LOGE("couldn't map [%8lx, %u]", offset, size); + if (size) { + /* NOTE: it's VERY important to not free allocations of size 0 + * because they're special as they don't have any record in the + * allocator and could alias some real allocation + * (their offset is zero). */ + allocator()->deallocate(offset); + } + } + } + return memory; +} + +void MemoryDealer::deallocate(size_t offset) +{ + allocator()->deallocate(offset); +} + +void MemoryDealer::dump(const char* what, uint32_t flags) const +{ + allocator()->dump(what, flags); +} + +const sp<HeapInterface>& MemoryDealer::heap() const { + return mHeap; +} + +const sp<AllocatorInterface>& MemoryDealer::allocator() const { + return mAllocator; +} + +// ---------------------------------------------------------------------------- + +// align all the memory blocks on a cache-line boundary +const int SimpleBestFitAllocator::kMemoryAlign = 32; + +SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) +{ + size_t pagesize = getpagesize(); + mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); + + chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); + mList.insertHead(node); +} + +SimpleBestFitAllocator::~SimpleBestFitAllocator() +{ + while(!mList.isEmpty()) { + delete mList.remove(mList.head()); + } +} + +size_t SimpleBestFitAllocator::size() const +{ + return mHeapSize; +} + +size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) +{ + Mutex::Autolock _l(mLock); + ssize_t offset = alloc(size, flags); + return offset; +} + +status_t SimpleBestFitAllocator::deallocate(size_t offset) +{ + Mutex::Autolock _l(mLock); + chunk_t const * const freed = dealloc(offset); + if (freed) { + return NO_ERROR; + } + return NAME_NOT_FOUND; +} + +ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) +{ + if (size == 0) { + return 0; + } + size = (size + kMemoryAlign-1) / kMemoryAlign; + chunk_t* free_chunk = 0; + chunk_t* cur = mList.head(); + + size_t pagesize = getpagesize(); + while (cur) { + int extra = 0; + if (flags & PAGE_ALIGNED) + extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; + + // best fit + if (cur->free && (cur->size >= (size+extra))) { + if ((!free_chunk) || (cur->size < free_chunk->size)) { + free_chunk = cur; + } + if (cur->size == size) { + break; + } + } + cur = cur->next; + } + + if (free_chunk) { + const size_t free_size = free_chunk->size; + free_chunk->free = 0; + free_chunk->size = size; + if (free_size > size) { + int extra = 0; + if (flags & PAGE_ALIGNED) + extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; + if (extra) { + chunk_t* split = new chunk_t(free_chunk->start, extra); + free_chunk->start += extra; + mList.insertBefore(free_chunk, split); + } + + LOGE_IF((flags&PAGE_ALIGNED) && + ((free_chunk->start*kMemoryAlign)&(pagesize-1)), + "PAGE_ALIGNED requested, but page is not aligned!!!"); + + const ssize_t tail_free = free_size - (size+extra); + if (tail_free > 0) { + chunk_t* split = new chunk_t( + free_chunk->start + free_chunk->size, tail_free); + mList.insertAfter(free_chunk, split); + } + } + return (free_chunk->start)*kMemoryAlign; + } + return NO_MEMORY; +} + +SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) +{ + start = start / kMemoryAlign; + chunk_t* cur = mList.head(); + while (cur) { + if (cur->start == start) { + LOG_FATAL_IF(cur->free, + "block at offset 0x%08lX of size 0x%08lX already freed", + cur->start*kMemoryAlign, cur->size*kMemoryAlign); + + // merge freed blocks together + chunk_t* freed = cur; + cur->free = 1; + do { + chunk_t* const p = cur->prev; + chunk_t* const n = cur->next; + if (p && (p->free || !cur->size)) { + freed = p; + p->size += cur->size; + mList.remove(cur); + delete cur; + } + cur = n; + } while (cur && cur->free); + + #ifndef NDEBUG + if (!freed->free) { + dump_l("dealloc (!freed->free)"); + } + #endif + LOG_FATAL_IF(!freed->free, + "freed block at offset 0x%08lX of size 0x%08lX is not free!", + freed->start * kMemoryAlign, freed->size * kMemoryAlign); + + return freed; + } + cur = cur->next; + } + return 0; +} + +void SimpleBestFitAllocator::dump(const char* what, uint32_t flags) const +{ + Mutex::Autolock _l(mLock); + dump_l(what, flags); +} + +void SimpleBestFitAllocator::dump_l(const char* what, uint32_t flags) const +{ + String8 result; + dump_l(result, what, flags); + LOGD("%s", result.string()); +} + +void SimpleBestFitAllocator::dump(String8& result, + const char* what, uint32_t flags) const +{ + Mutex::Autolock _l(mLock); + dump_l(result, what, flags); +} + +void SimpleBestFitAllocator::dump_l(String8& result, + const char* what, uint32_t flags) const +{ + size_t size = 0; + int32_t i = 0; + chunk_t const* cur = mList.head(); + + const size_t SIZE = 256; + char buffer[SIZE]; + snprintf(buffer, SIZE, " %s (%p, size=%u)\n", + what, this, (unsigned int)mHeapSize); + + result.append(buffer); + + while (cur) { + const char* errs[] = {"", "| link bogus NP", + "| link bogus PN", "| link bogus NP+PN" }; + int np = ((cur->next) && cur->next->prev != cur) ? 1 : 0; + int pn = ((cur->prev) && cur->prev->next != cur) ? 2 : 0; + + snprintf(buffer, SIZE, " %3u: %08x | 0x%08X | 0x%08X | %s %s\n", + i, int(cur), int(cur->start*kMemoryAlign), + int(cur->size*kMemoryAlign), + int(cur->free) ? "F" : "A", + errs[np|pn]); + + result.append(buffer); + + if (!cur->free) + size += cur->size*kMemoryAlign; + + i++; + cur = cur->next; + } + snprintf(buffer, SIZE, " size allocated: %u (%u KB)\n", int(size), int(size/1024)); + result.append(buffer); +} + +// ---------------------------------------------------------------------------- + +SharedHeap::SharedHeap() + : HeapInterface(), MemoryHeapBase() +{ +} + +SharedHeap::SharedHeap(size_t size, uint32_t flags, char const * name) + : MemoryHeapBase(size, flags, name) +{ +} + +SharedHeap::~SharedHeap() +{ +} + +sp<IMemory> SharedHeap::mapMemory(size_t offset, size_t size) +{ + return new SimpleMemory(this, offset, size); +} + + +SimpleMemory::SimpleMemory(const sp<IMemoryHeap>& heap, + ssize_t offset, size_t size) + : MemoryBase(heap, offset, size) +{ +#ifndef NDEBUG + void* const start_ptr = (void*)(intptr_t(heap->base()) + offset); + memset(start_ptr, 0xda, size); +#endif +} + +SimpleMemory::~SimpleMemory() +{ + size_t freedOffset = getOffset(); + size_t freedSize = getSize(); + + // keep the size to unmap in excess + size_t pagesize = getpagesize(); + size_t start = freedOffset; + size_t end = start + freedSize; + start &= ~(pagesize-1); + end = (end + pagesize-1) & ~(pagesize-1); + + // give back to the kernel the pages we don't need + size_t free_start = freedOffset; + size_t free_end = free_start + freedSize; + if (start < free_start) + start = free_start; + if (end > free_end) + end = free_end; + start = (start + pagesize-1) & ~(pagesize-1); + end &= ~(pagesize-1); + + if (start < end) { + void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start); + size_t size = end-start; + +#ifndef NDEBUG + memset(start_ptr, 0xdf, size); +#endif + + // MADV_REMOVE is not defined on Dapper based Goobuntu +#ifdef MADV_REMOVE + if (size) { + int err = madvise(start_ptr, size, MADV_REMOVE); + LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s", + start_ptr, size, err<0 ? strerror(errno) : "Ok"); + } +#endif + } +} + +}; // namespace android diff --git a/libs/binder/MemoryHeapPmem.cpp b/libs/binder/MemoryHeapPmem.cpp index 16e92f9..5cc60f8 100644 --- a/libs/binder/MemoryHeapPmem.cpp +++ b/libs/binder/MemoryHeapPmem.cpp @@ -127,7 +127,11 @@ void SubRegionMemory::revoke() MemoryHeapPmem::MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap, uint32_t flags) +#ifdef USE_ECLAIR_MEMORYDEALER + : HeapInterface(), MemoryHeapBase() +#else : MemoryHeapBase() +#endif { char const * const device = pmemHeap->getDevice(); #if HAVE_ANDROID_OS |