diff options
author | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2012-09-24 19:32:23 +0100 |
---|---|---|
committer | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2012-09-24 19:32:40 +0100 |
commit | a17cf4c0b406769f20aa6a541c4649ceb7059124 (patch) | |
tree | b5c896b49644fe271e76ffee5b96095961a370aa | |
parent | d39f52491364217e40aca4fb06ed9f7903af60f0 (diff) | |
download | system_core-a17cf4c0b406769f20aa6a541c4649ceb7059124.zip system_core-a17cf4c0b406769f20aa6a541c4649ceb7059124.tar.gz system_core-a17cf4c0b406769f20aa6a541c4649ceb7059124.tar.bz2 |
Revert "Upgrade to dlmalloc 2.8.5."
These changes to malloc were breaking some blobs...
This reverts commit 5d382954131d2ed5e98438fd22e87506e9441901.
Change-Id: Idbb88c5f18e89c76251dd0a5038ec75e22c197b2
-rw-r--r-- | include/cutils/mspace.h | 128 | ||||
-rw-r--r-- | libcutils/Android.mk | 1 | ||||
-rw-r--r-- | libcutils/dlmalloc_stubs.c | 20 | ||||
-rw-r--r-- | libcutils/mspace.c | 286 | ||||
-rw-r--r-- | libpixelflinger/codeflinger/CodeCache.cpp | 89 | ||||
-rw-r--r-- | libpixelflinger/codeflinger/CodeCache.h | 4 |
6 files changed, 448 insertions, 80 deletions
diff --git a/include/cutils/mspace.h b/include/cutils/mspace.h new file mode 100644 index 0000000..93fe48e --- /dev/null +++ b/include/cutils/mspace.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 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. + */ + +/* A wrapper file for dlmalloc.h that defines prototypes for the + * mspace_*() functions, which provide an interface for creating + * multiple heaps. + */ + +#ifndef MSPACE_H_ +#define MSPACE_H_ + +/* It's a pain getting the mallinfo stuff to work + * with Linux, OSX, and klibc, so just turn it off + * for now. + * TODO: make mallinfo work + */ +#define NO_MALLINFO 1 + +/* Allow setting the maximum heap footprint. + */ +#define USE_MAX_ALLOWED_FOOTPRINT 1 + +#define USE_CONTIGUOUS_MSPACES 1 +#if USE_CONTIGUOUS_MSPACES +#define HAVE_MMAP 0 +#define HAVE_MORECORE 1 +#define MORECORE_CONTIGUOUS 0 +#endif + +#define MSPACES 1 +#define ONLY_MSPACES 1 +#include "../../../../bionic/libc/bionic/dlmalloc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mspace_usable_size(void* p); + + Returns the number of bytes you can actually use in + an allocated chunk, which may be more than you requested (although + often not) due to alignment and minimum size constraints. + You can use this many bytes without worrying about + overwriting other allocated objects. This is not a particularly great + programming practice. mspace_usable_size can be more useful in + debugging and assertions, for example: + + p = mspace_malloc(msp, n); + assert(mspace_usable_size(msp, p) >= 256); +*/ +size_t mspace_usable_size(mspace, const void*); + +#if USE_CONTIGUOUS_MSPACES +/* + Similar to create_mspace(), but the underlying memory is + guaranteed to be contiguous. No more than max_capacity + bytes is ever allocated to the mspace. + */ +mspace create_contiguous_mspace(size_t starting_capacity, size_t max_capacity, + int locked); + +/* + Identical to create_contiguous_mspace, but labels the mapping 'mspace/name' + instead of 'mspace' +*/ +mspace create_contiguous_mspace_with_name(size_t starting_capacity, + size_t max_capacity, int locked, const char *name); + +/* + Identical to create_contiguous_mspace, but uses previously mapped memory. +*/ +mspace create_contiguous_mspace_with_base(size_t starting_capacity, + size_t max_capacity, int locked, void *base); + +size_t destroy_contiguous_mspace(mspace msp); + +/* + Returns the position of the "break" within the given mspace. +*/ +void *contiguous_mspace_sbrk0(mspace msp); +#endif + +/* + Call the handler for each block in the specified mspace. + chunkptr and chunklen refer to the heap-level chunk including + the chunk overhead, and userptr and userlen refer to the + user-usable part of the chunk. If the chunk is free, userptr + will be NULL and userlen will be 0. userlen is not guaranteed + to be the same value passed into malloc() for a given chunk; + it is >= the requested size. + */ +void mspace_walk_heap(mspace msp, + void(*handler)(const void *chunkptr, size_t chunklen, + const void *userptr, size_t userlen, void *arg), void *harg); + +/* + mspace_walk_free_pages(handler, harg) + + Calls the provided handler on each free region in the specified + mspace. The memory between start and end are guaranteed not to + contain any important data, so the handler is free to alter the + contents in any way. This can be used to advise the OS that large + free regions may be swapped out. + + The value in harg will be passed to each call of the handler. + */ +void mspace_walk_free_pages(mspace msp, + void(*handler)(void *start, void *end, void *arg), void *harg); + +#ifdef __cplusplus +}; /* end of extern "C" */ +#endif + +#endif /* MSPACE_H_ */ diff --git a/libcutils/Android.mk b/libcutils/Android.mk index 00d44ec..6a2ba66 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -75,6 +75,7 @@ ifeq ($(WINDOWS_HOST_ONLY),1) else commonSources += \ abort_socket.c \ + mspace.c \ selector.c \ tztime.c \ zygote.c diff --git a/libcutils/dlmalloc_stubs.c b/libcutils/dlmalloc_stubs.c index c327a55..1ced147 100644 --- a/libcutils/dlmalloc_stubs.c +++ b/libcutils/dlmalloc_stubs.c @@ -14,22 +14,16 @@ * limitations under the License. */ -#include "../../../bionic/libc/bionic/dlmalloc.h" -#include "cutils/log.h" - -/* - * Stubs for functions defined in bionic/libc/bionic/dlmalloc.c. These - * are used in host builds, as the host libc will not contain these - * functions. +/* No-op stubs for functions defined in system/bionic/bionic/dlmalloc.c. */ -void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*), - void* arg) +void dlmalloc_walk_free_pages() +{ +} + +void dlmalloc_walk_heap() { - ALOGW("Called host unimplemented stub: dlmalloc_inspect_all"); } -int dlmalloc_trim(size_t unused) +void dlmalloc_trim() { - ALOGW("Called host unimplemented stub: dlmalloc_trim"); - return 0; } diff --git a/libcutils/mspace.c b/libcutils/mspace.c new file mode 100644 index 0000000..6d3b35c --- /dev/null +++ b/libcutils/mspace.c @@ -0,0 +1,286 @@ +/* Copyright 2006 The Android Open Source Project */ + +/* A wrapper file for dlmalloc.c that compiles in the + * mspace_*() functions, which provide an interface for + * creating multiple heaps. + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdint.h> +#include <sys/ioctl.h> + +#include <cutils/ashmem.h> + +/* It's a pain getting the mallinfo stuff to work + * with Linux, OSX, and klibc, so just turn it off + * for now. + * TODO: make mallinfo work + */ +#define NO_MALLINFO 1 + +/* Allow setting the maximum heap footprint. + */ +#define USE_MAX_ALLOWED_FOOTPRINT 1 + +/* Don't try to trim memory. + * TODO: support this. + */ +#define MORECORE_CANNOT_TRIM 1 + +/* Use mmap()d anonymous memory to guarantee + * that an mspace is contiguous. + * + * create_mspace() won't work right if this is + * defined, so hide the definition of it and + * break any users at build time. + */ +#define USE_CONTIGUOUS_MSPACES 1 +#if USE_CONTIGUOUS_MSPACES +/* This combination of settings forces sys_alloc() + * to always use MORECORE(). It won't expect the + * results to be contiguous, but we'll guarantee + * that they are. + */ +#define HAVE_MMAP 0 +#define HAVE_MORECORE 1 +#define MORECORE_CONTIGUOUS 0 +/* m is always the appropriate local when MORECORE() is called. */ +#define MORECORE(S) contiguous_mspace_morecore(m, S) +#define create_mspace HIDDEN_create_mspace_HIDDEN +#define destroy_mspace HIDDEN_destroy_mspace_HIDDEN +typedef struct malloc_state *mstate0; +static void *contiguous_mspace_morecore(mstate0 m, ssize_t nb); +#endif + +#define MSPACES 1 +#define ONLY_MSPACES 1 +#include "../../../bionic/libc/bionic/dlmalloc.c" + +#ifndef PAGESIZE +#define PAGESIZE mparams.page_size +#endif + +#define ALIGN_UP(p, alignment) \ + (((uintptr_t)(p) + (alignment)-1) & ~((alignment)-1)) + +/* A direct copy of dlmalloc_usable_size(), + * which isn't compiled in when ONLY_MSPACES is set. + * The mspace parameter isn't actually necessary, + * but we include it to be consistent with the + * rest of the mspace_*() functions. + */ +size_t mspace_usable_size(mspace _unused, const void* mem) { + if (mem != 0) { + const mchunkptr p = mem2chunk(mem); + if (cinuse(p)) + return chunksize(p) - overhead_for(p); + } + return 0; +} + +#if USE_CONTIGUOUS_MSPACES +#include <sys/mman.h> +#include <limits.h> + +#define CONTIG_STATE_MAGIC 0xf00dd00d +struct mspace_contig_state { + unsigned int magic; + char *brk; + char *top; + mspace m; +}; + +static void *contiguous_mspace_morecore(mstate m, ssize_t nb) { + struct mspace_contig_state *cs; + char *oldbrk; + const unsigned int pagesize = PAGESIZE; + + cs = (struct mspace_contig_state *)((uintptr_t)m & ~(pagesize-1)); + assert(cs->magic == CONTIG_STATE_MAGIC); + assert(cs->m == m); +assert(nb >= 0); //xxx deal with the trim case + + oldbrk = cs->brk; + if (nb > 0) { + /* Break to the first page boundary that satisfies the request. + */ + char *newbrk = (char *)ALIGN_UP(oldbrk + nb, pagesize); + if (newbrk > cs->top) + return CMFAIL; + + /* Update the protection on the underlying memory. + * Pages we've given to dlmalloc are read/write, and + * pages we haven't are not accessable (read or write + * will cause a seg fault). + */ + if (mprotect(cs, newbrk - (char *)cs, PROT_READ | PROT_WRITE) < 0) + return CMFAIL; + if (newbrk != cs->top) { + if (mprotect(newbrk, cs->top - newbrk, PROT_NONE) < 0) + return CMFAIL; + } + + cs->brk = newbrk; + + /* Make sure that dlmalloc will merge this block with the + * initial block that was passed to create_mspace_with_base(). + * We don't care about extern vs. non-extern, so just clear it. + */ + m->seg.sflags &= ~EXTERN_BIT; + } + + return oldbrk; +} + +mspace create_contiguous_mspace_with_base(size_t starting_capacity, + size_t max_capacity, int locked, void *base) { + struct mspace_contig_state *cs; + unsigned int pagesize; + mstate m; + + init_mparams(); + pagesize = PAGESIZE; + assert(starting_capacity <= max_capacity); + assert(((uintptr_t)base & (pagesize-1)) == 0); + assert(((uintptr_t)max_capacity & (pagesize-1)) == 0); + starting_capacity = (size_t)ALIGN_UP(starting_capacity, pagesize); + + /* Make the first page read/write. dlmalloc needs to use that page. + */ + if (mprotect(base, starting_capacity, PROT_READ | PROT_WRITE) < 0) { + goto error; + } + + /* Create the mspace, pointing to the memory given. + */ + m = create_mspace_with_base((char *)base + sizeof(*cs), starting_capacity, + locked); + if (m == (mspace)0) { + goto error; + } + /* Make sure that m is in the same page as base. + */ + assert(((uintptr_t)m & (uintptr_t)~(pagesize-1)) == (uintptr_t)base); + /* Use some space for the information that our MORECORE needs. + */ + cs = (struct mspace_contig_state *)base; + + /* Find out exactly how much of the memory the mspace + * is using. + */ + cs->brk = m->seg.base + m->seg.size; + cs->top = (char *)base + max_capacity; + + assert((char *)base <= cs->brk); + assert(cs->brk <= cs->top); + /* Prevent access to the memory we haven't handed out yet. + */ + if (cs->brk != cs->top) { + /* mprotect() requires page-aligned arguments, but it's possible + * for cs->brk not to be page-aligned at this point. + */ + char *prot_brk = (char *)ALIGN_UP(cs->brk, pagesize); + if ((mprotect(base, prot_brk - (char *)base, PROT_READ | PROT_WRITE) < 0) || + (mprotect(prot_brk, cs->top - prot_brk, PROT_NONE) < 0)) { + goto error; + } + } + + cs->m = m; + cs->magic = CONTIG_STATE_MAGIC; + + return (mspace)m; + +error: + return (mspace)0; +} + + +mspace create_contiguous_mspace_with_name(size_t starting_capacity, + size_t max_capacity, int locked, char const *name) { + int fd, ret; + char buf[ASHMEM_NAME_LEN] = "mspace"; + void *base; + unsigned int pagesize; + mstate m; + + if (starting_capacity > max_capacity) + return (mspace)0; + + init_mparams(); + pagesize = PAGESIZE; + + /* Create the anonymous memory that will back the mspace. + * This reserves all of the virtual address space we could + * ever need. Physical pages will be mapped as the memory + * is touched. + * + * Align max_capacity to a whole page. + */ + max_capacity = (size_t)ALIGN_UP(max_capacity, pagesize); + + if (name) + snprintf(buf, sizeof(buf), "mspace/%s", name); + fd = ashmem_create_region(buf, max_capacity); + if (fd < 0) + return (mspace)0; + + base = mmap(NULL, max_capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + close(fd); + if (base == MAP_FAILED) + return (mspace)0; + + /* Make sure that base is at the beginning of a page. + */ + assert(((uintptr_t)base & (pagesize-1)) == 0); + + m = create_contiguous_mspace_with_base(starting_capacity, max_capacity, + locked, base); + if (m == 0) { + munmap(base, max_capacity); + } + return m; +} + +mspace create_contiguous_mspace(size_t starting_capacity, + size_t max_capacity, int locked) { + return create_contiguous_mspace_with_name(starting_capacity, + max_capacity, locked, NULL); +} + +size_t destroy_contiguous_mspace(mspace msp) { + mstate ms = (mstate)msp; + + if (ok_magic(ms)) { + struct mspace_contig_state *cs; + size_t length; + const unsigned int pagesize = PAGESIZE; + + cs = (struct mspace_contig_state *)((uintptr_t)ms & ~(pagesize-1)); + assert(cs->magic == CONTIG_STATE_MAGIC); + assert(cs->m == ms); + + length = cs->top - (char *)cs; + if (munmap((char *)cs, length) != 0) + return length; + } + else { + USAGE_ERROR_ACTION(ms, ms); + } + return 0; +} + +void *contiguous_mspace_sbrk0(mspace msp) { + struct mspace_contig_state *cs; + mstate ms; + const unsigned int pagesize = PAGESIZE; + + ms = (mstate)msp; + cs = (struct mspace_contig_state *)((uintptr_t)ms & ~(pagesize-1)); + assert(cs->magic == CONTIG_STATE_MAGIC); + assert(cs->m == ms); + return cs->brk; +} +#endif diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp index 60fc771..a713feb 100644 --- a/libpixelflinger/codeflinger/CodeCache.cpp +++ b/libpixelflinger/codeflinger/CodeCache.cpp @@ -23,13 +23,10 @@ #include <sys/mman.h> #include <cutils/log.h> -#include <cutils/ashmem.h> #include <cutils/atomic.h> #include "codeflinger/CodeCache.h" -#define LOG_TAG "CodeCache" - namespace android { // ---------------------------------------------------------------------------- @@ -41,72 +38,12 @@ namespace android { // ---------------------------------------------------------------------------- -// A dlmalloc mspace is used to manage the code cache over a mmaped region. -#define HAVE_MMAP 0 -#define HAVE_MREMAP 0 -#define HAVE_MORECORE 0 -#define MALLOC_ALIGNMENT 16 -#define MSPACES 1 -#define NO_MALLINFO 1 -#define ONLY_MSPACES 1 -// Custom heap error handling. -#define PROCEED_ON_ERROR 0 -static void heap_error(const char* msg, const char* function, void* p); -#define CORRUPTION_ERROR_ACTION(m) \ - heap_error("HEAP MEMORY CORRUPTION", __FUNCTION__, NULL) -#define USAGE_ERROR_ACTION(m,p) \ - heap_error("ARGUMENT IS INVALID HEAP ADDRESS", __FUNCTION__, p) - - -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#pragma GCC diagnostic ignored "-Wempty-body" -#include "../../../../bionic/libc/upstream-dlmalloc/malloc.c" -#pragma GCC diagnostic warning "-Wstrict-aliasing" -#pragma GCC diagnostic warning "-Wempty-body" - -static void heap_error(const char* msg, const char* function, void* p) { - ALOG(LOG_FATAL, LOG_TAG, "@@@ ABORTING: CODE FLINGER: %s IN %s addr=%p", - msg, function, p); - /* So that we can get a memory dump around p */ - *((int **) 0xdeadbaad) = (int *) p; -} - -// ---------------------------------------------------------------------------- - -static void* gExecutableStore = NULL; -static mspace gMspace = NULL; -const size_t kMaxCodeCacheCapacity = 1024 * 1024; - -static mspace getMspace() -{ - if (gExecutableStore == NULL) { - int fd = ashmem_create_region("CodeFlinger code cache", - kMaxCodeCacheCapacity); - LOG_ALWAYS_FATAL_IF(fd < 0, - "Creating code cache, ashmem_create_region " - "failed with error '%s'", strerror(errno)); - gExecutableStore = mmap(NULL, kMaxCodeCacheCapacity, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE, fd, 0); - LOG_ALWAYS_FATAL_IF(gExecutableStore == NULL, - "Creating code cache, mmap failed with error " - "'%s'", strerror(errno)); - close(fd); - gMspace = create_mspace_with_base(gExecutableStore, kMaxCodeCacheCapacity, - /*locked=*/ false); - mspace_set_footprint_limit(gMspace, kMaxCodeCacheCapacity); - } - return gMspace; -} - Assembly::Assembly(size_t size) : mCount(1), mSize(0) { mBase = (uint32_t*)mspace_malloc(getMspace(), size); - LOG_ALWAYS_FATAL_IF(mBase == NULL, - "Failed to create Assembly of size %zd in executable " - "store of size %zd", size, kMaxCodeCacheCapacity); mSize = size; + ensureMbaseExecutable(); } Assembly::~Assembly() @@ -140,13 +77,31 @@ uint32_t* Assembly::base() const ssize_t Assembly::resize(size_t newSize) { mBase = (uint32_t*)mspace_realloc(getMspace(), mBase, newSize); - LOG_ALWAYS_FATAL_IF(mBase == NULL, - "Failed to resize Assembly to %zd in code cache " - "of size %zd", newSize, kMaxCodeCacheCapacity); mSize = newSize; + ensureMbaseExecutable(); return size(); } +mspace Assembly::getMspace() +{ + static mspace msp = create_contiguous_mspace(2 * 1024, 1024 * 1024, /*locked=*/ false); + return msp; +} + +void Assembly::ensureMbaseExecutable() +{ + long pagesize = sysconf(_SC_PAGESIZE); + long pagemask = ~(pagesize - 1); // assumes pagesize is a power of 2 + + uint32_t* pageStart = (uint32_t*) (((uintptr_t) mBase) & pagemask); + size_t adjustedLength = (mBase - pageStart) * sizeof(uint32_t) + mSize; + + if (mBase && mprotect(pageStart, adjustedLength, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { + mspace_free(getMspace(), mBase); + mBase = NULL; + } +} + // ---------------------------------------------------------------------------- CodeCache::CodeCache(size_t size) diff --git a/libpixelflinger/codeflinger/CodeCache.h b/libpixelflinger/codeflinger/CodeCache.h index 54fd69b..aaafd26 100644 --- a/libpixelflinger/codeflinger/CodeCache.h +++ b/libpixelflinger/codeflinger/CodeCache.h @@ -22,6 +22,7 @@ #include <stdint.h> #include <pthread.h> #include <sys/types.h> +#include <cutils/mspace.h> #include "tinyutils/KeyedVector.h" #include "tinyutils/smartpointer.h" @@ -67,6 +68,9 @@ public: typedef void weakref_type; private: + static mspace getMspace(); + void ensureMbaseExecutable(); + mutable int32_t mCount; uint32_t* mBase; size_t mSize; |