/* * Copyright (c) 2011, Code Aurora Forum. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of Code Aurora Forum, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "ashmemalloc.h" using gralloc::AshmemAlloc; int AshmemAlloc::alloc_buffer(alloc_data& data) { int err = 0; int fd = -1; void* base = 0; int offset = 0; char name[ASHMEM_NAME_LEN]; snprintf(name, ASHMEM_NAME_LEN, "gralloc-buffer-%x", data.pHandle); int prot = PROT_READ | PROT_WRITE; fd = ashmem_create_region(name, data.size); if (fd < 0) { LOGE("couldn't create ashmem (%s)", strerror(errno)); err = -errno; } else { if (ashmem_set_prot_region(fd, prot) < 0) { LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)", fd, prot, strerror(errno)); close(fd); err = -errno; } else { base = mmap(0, data.size, prot, MAP_SHARED|MAP_POPULATE|MAP_LOCKED, fd, 0); if (base == MAP_FAILED) { LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)", fd, data.size, prot, strerror(errno)); close(fd); err = -errno; } else { memset((char*)base + offset, 0, data.size); } } } if(err == 0) { data.fd = fd; data.base = base; data.offset = offset; clean_buffer(base, data.size, offset, fd); } return err; } int AshmemAlloc::free_buffer(void* base, size_t size, int offset, int fd) { LOGD("%s:Freeing buffer size=%d base=%p fd=%d PID=%d", __FUNCTION__, size, base, fd, getpid()); int err = 0; if(!base) { LOGE("Invalid free"); return -EINVAL; } err = unmap_buffer(base, size, offset); close(fd); return err; } int AshmemAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) { LOGD("%s: Mapping buffer fd=%d size=%d PID=%d", __FUNCTION__, fd, size, getpid()); int err = 0; void *base = 0; if (err) return err; base = mmap(0, size, PROT_READ| PROT_WRITE, MAP_SHARED|MAP_POPULATE, fd, 0); *pBase = base; if(base == MAP_FAILED) { LOGD("%s: Failed to map memory in the client: %s", __FUNCTION__, strerror(errno)); err = -errno; } else { LOGD("%s: Successfully mapped %d bytes", __FUNCTION__, size); } return err; } int AshmemAlloc::unmap_buffer(void *base, size_t size, int offset) { LOGD("%s: Unmapping buffer at address %p", __FUNCTION__, base); int err = munmap(base, size); if(err) { LOGE("%s: Failed to unmap memory at %p: %s", __FUNCTION__, base, strerror(errno)); } return err; } int AshmemAlloc::clean_buffer(void *base, size_t size, int offset, int fd) { // LOGD("%s: Clean buffer fd=%d base = %p size=%d PID=%d", __FUNCTION__, // fd, base, size, getpid()); int err = 0; if (ioctl(fd, ASHMEM_CACHE_FLUSH_RANGE, NULL)) { LOGE("ASHMEM_CACHE_FLUSH_RANGE failed fd = %d", fd); } return err; }