diff options
-rw-r--r-- | include/cutils/mspace.h | 6 | ||||
-rw-r--r-- | libcutils/mspace.c | 107 |
2 files changed, 73 insertions, 40 deletions
diff --git a/include/cutils/mspace.h b/include/cutils/mspace.h index 33410c1..e6e4047 100644 --- a/include/cutils/mspace.h +++ b/include/cutils/mspace.h @@ -80,6 +80,12 @@ mspace create_contiguous_mspace(size_t starting_capacity, size_t max_capacity, 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); #endif diff --git a/libcutils/mspace.c b/libcutils/mspace.c index 2110b43..63b199d 100644 --- a/libcutils/mspace.c +++ b/libcutils/mspace.c @@ -134,68 +134,47 @@ assert(nb >= 0); //xxx deal with the trim case return oldbrk; } -mspace create_contiguous_mspace_with_name(size_t starting_capacity, - size_t max_capacity, int locked, char const * name) { - int fd, ret; +mspace create_contiguous_mspace_with_base(size_t starting_capacity, + size_t max_capacity, int locked, void *base) { struct mspace_contig_state *cs; - 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(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); - /* Reserve some space for the information that our MORECORE needs. + /* Make the first page read/write. dlmalloc needs to use that page. */ - cs = base; + if (mprotect(base, starting_capacity, PROT_READ | PROT_WRITE) < 0) { + goto error; + } - /* Create the mspace, pointing to the memory we just reserved. + /* Create the mspace, pointing to the memory given. */ m = create_mspace_with_base((char *)base + sizeof(*cs), starting_capacity, locked); - if (m == (mspace)0) + if (m == (mspace)0) { goto error; - - /* Make sure that m is in the same page as cs. + } + /* 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) { @@ -203,8 +182,10 @@ mspace create_contiguous_mspace_with_name(size_t starting_capacity, * for cs->brk not to be page-aligned at this point. */ char *prot_brk = (char *)ALIGN_UP(cs->brk, pagesize); - if (mprotect(prot_brk, cs->top - prot_brk, PROT_NONE) < 0) + 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; @@ -213,10 +194,56 @@ mspace create_contiguous_mspace_with_name(size_t starting_capacity, return (mspace)m; error: - munmap(base, max_capacity); 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, |