1f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis/* 2f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * Copyright (C) 2010 The Android Open Source Project 3f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * 4f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * Licensed under the Apache License, Version 2.0 (the "License"); 5f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * you may not use this file except in compliance with the License. 6f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * You may obtain a copy of the License at 7f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * 8f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * http://www.apache.org/licenses/LICENSE-2.0 9f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * 10f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * Unless required by applicable law or agreed to in writing, software 11f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * distributed under the License is distributed on an "AS IS" BASIS, 12f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * See the License for the specific language governing permissions and 14f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis * limitations under the License. 15f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis */ 16f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 17f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis//#define LOG_NDEBUG 0 18f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 19f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <limits.h> 20f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <unistd.h> 21f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <fcntl.h> 22f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <pthread.h> 23f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <stdlib.h> 24f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <string.h> 25f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 26f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <sys/mman.h> 27f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 28f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <cutils/log.h> 29f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include <cutils/ashmem.h> 30f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 31f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include "gralloc_priv.h" 32f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis#include "pmemalloc.h" 33f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 34f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 3522f2554680715d1ea993409217a4a21f652ef130Steve Block#define BEGIN_FUNC ALOGV("%s begin", __PRETTY_FUNCTION__) 3622f2554680715d1ea993409217a4a21f652ef130Steve Block#define END_FUNC ALOGV("%s end", __PRETTY_FUNCTION__) 37f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 38f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 39f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisstatic int get_open_flags(int usage) { 40f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int openFlags = O_RDWR | O_SYNC; 41f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis uint32_t uread = usage & GRALLOC_USAGE_SW_READ_MASK; 42f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis uint32_t uwrite = usage & GRALLOC_USAGE_SW_WRITE_MASK; 43f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (uread == GRALLOC_USAGE_SW_READ_OFTEN || 44f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis uwrite == GRALLOC_USAGE_SW_WRITE_OFTEN) { 45f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis openFlags &= ~O_SYNC; 46f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 47f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return openFlags; 48f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 49f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 50f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie GennisPmemAllocator::~PmemAllocator() 51f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 52f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 53f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 54f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 55f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 56f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 57f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie GennisPmemUserspaceAllocator::PmemUserspaceAllocator(Deps& deps, Deps::Allocator& allocator, const char* pmemdev): 58f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis deps(deps), 59f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis allocator(allocator), 60f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis pmemdev(pmemdev), 61f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis master_fd(MASTER_FD_INIT) 62f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 63f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 64f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis pthread_mutex_init(&lock, NULL); 65f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 66f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 67f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 68f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 69f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie GennisPmemUserspaceAllocator::~PmemUserspaceAllocator() 70f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 71f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 72f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 73f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 74f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 75f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 76f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisvoid* PmemUserspaceAllocator::get_base_address() { 77f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 78f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 79f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return master_base; 80f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 81f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 82f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 83f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint PmemUserspaceAllocator::init_pmem_area_locked() 84f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 85f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 86f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int err = 0; 87f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int fd = deps.open(pmemdev, O_RDWR, 0); 88f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (fd >= 0) { 89f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis size_t size = 0; 90f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = deps.getPmemTotalSize(fd, &size); 91f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (err < 0) { 92c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block ALOGE("%s: PMEM_GET_TOTAL_SIZE failed (%d), limp mode", pmemdev, 93f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err); 94f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis size = 8<<20; // 8 MiB 95f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 96f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis allocator.setSize(size); 97f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 98f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 99f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 0); 100f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (base == MAP_FAILED) { 101c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block ALOGE("%s: failed to map pmem master fd: %s", pmemdev, 102f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis strerror(deps.getErrno())); 103f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = -deps.getErrno(); 104f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis base = 0; 105f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis deps.close(fd); 106f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis fd = -1; 107f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } else { 108f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis master_fd = fd; 109f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis master_base = base; 110f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 111f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } else { 112c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block ALOGE("%s: failed to open pmem device: %s", pmemdev, 113f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis strerror(deps.getErrno())); 114f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = -deps.getErrno(); 115f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 116f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 117f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return err; 118f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 119f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 120f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 121f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint PmemUserspaceAllocator::init_pmem_area() 122f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 123f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 124f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis pthread_mutex_lock(&lock); 125f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int err = master_fd; 126f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (err == MASTER_FD_INIT) { 127f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // first time, try to initialize pmem 128f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = init_pmem_area_locked(); 129f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (err) { 130c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block ALOGE("%s: failed to initialize pmem area", pmemdev); 131f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis master_fd = err; 132f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 133f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } else if (err < 0) { 134f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // pmem couldn't be initialized, never use it 135f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } else { 136f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // pmem OK 137f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = 0; 138f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 139f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis pthread_mutex_unlock(&lock); 140f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 141f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return err; 142f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 143f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 144f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 145f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, 146f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis void** pBase, int* pOffset, int* pFd) 147f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 148f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 149f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int err = init_pmem_area(); 150f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (err == 0) { 151f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis void* base = master_base; 152f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int offset = allocator.allocate(size); 153f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (offset < 0) { 154f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // no more pmem memory 155c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block ALOGE("%s: no more pmem available", pmemdev); 156f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = -ENOMEM; 157f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } else { 158f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int openFlags = get_open_flags(usage); 159f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 160f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block //ALOGD("%s: allocating pmem at offset 0x%p", pmemdev, offset); 161f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 162f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // now create the "sub-heap" 163f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int fd = deps.open(pmemdev, openFlags, 0); 164f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = fd < 0 ? fd : 0; 165f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 166f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // and connect to it 167f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (err == 0) 168f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = deps.connectPmem(fd, master_fd); 169f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 170f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // and make it available to the client process 171f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (err == 0) 172f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = deps.mapPmem(fd, offset, size); 173f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 174f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (err < 0) { 175c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block ALOGE("%s: failed to initialize pmem sub-heap: %d", pmemdev, 176f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err); 177f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = -deps.getErrno(); 178f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis deps.close(fd); 179f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis allocator.deallocate(offset); 180f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis fd = -1; 181f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } else { 18222f2554680715d1ea993409217a4a21f652ef130Steve Block ALOGV("%s: mapped fd %d at offset %d, size %d", pmemdev, fd, offset, size); 183f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis memset((char*)base + offset, 0, size); 184f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *pBase = base; 185f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *pOffset = offset; 186f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *pFd = fd; 187f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 188f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block //ALOGD_IF(!err, "%s: allocating pmem size=%d, offset=%d", pmemdev, size, offset); 189f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 190f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 191f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 192f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return err; 193f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 194f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 195f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 196f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint PmemUserspaceAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd) 197f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 198f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 199f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int err = 0; 200f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (fd >= 0) { 201f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int err = deps.unmapPmem(fd, offset, size); 202c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block ALOGE_IF(err<0, "PMEM_UNMAP failed (%s), fd=%d, sub.offset=%u, " 203f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis "sub.size=%u", strerror(deps.getErrno()), fd, offset, size); 204f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (err == 0) { 205f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // we can't deallocate the memory in case of UNMAP failure 206f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // because it would give that process access to someone else's 207f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // surfaces, which would be a security breach. 208f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis allocator.deallocate(offset); 209f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 210f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 211f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 212f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return err; 213f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 214f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 215f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie GennisPmemUserspaceAllocator::Deps::Allocator::~Allocator() 216f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 217f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 218f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 219f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 220f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 221f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie GennisPmemUserspaceAllocator::Deps::~Deps() 222f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 223f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 224f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 225f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 226f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 227f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie GennisPmemKernelAllocator::PmemKernelAllocator(Deps& deps, const char* pmemdev): 228f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis deps(deps), 229f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis pmemdev(pmemdev) 230f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 231f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 232f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 233f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 234f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 235f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 236f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie GennisPmemKernelAllocator::~PmemKernelAllocator() 237f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 238f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 239f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 240f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 241f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 242f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 243f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisvoid* PmemKernelAllocator::get_base_address() { 244f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 245f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 246f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return 0; 247f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 248f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 249f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 250f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisstatic unsigned clp2(unsigned x) { 251f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis x = x - 1; 252f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis x = x | (x >> 1); 253f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis x = x | (x >> 2); 254f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis x = x | (x >> 4); 255f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis x = x | (x >> 8); 256f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis x = x | (x >>16); 257f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return x + 1; 258f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 259f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 260f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 261f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, 262f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis void** pBase,int* pOffset, int* pFd) 263f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 264f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 265f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 266f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *pBase = 0; 267f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *pOffset = 0; 268f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *pFd = -1; 269f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 270f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int err; 271f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int openFlags = get_open_flags(usage); 272f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int fd = deps.open(pmemdev, openFlags, 0); 273f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (fd < 0) { 274f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = -deps.getErrno(); 275f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 276f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return err; 277f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 278f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 279f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // The size should already be page aligned, now round it up to a power of 2. 280f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis size = clp2(size); 281f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 282f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 283f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (base == MAP_FAILED) { 284c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block ALOGE("%s: failed to map pmem fd: %s", pmemdev, 285f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis strerror(deps.getErrno())); 286f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = -deps.getErrno(); 287f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis deps.close(fd); 288f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 289f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return err; 290f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 291f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 292f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis memset(base, 0, size); 293f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 294f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *pBase = base; 295f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *pOffset = 0; 296f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis *pFd = fd; 297f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 298f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 299f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return 0; 300f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 301f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 302f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 303f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennisint PmemKernelAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd) 304f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 305f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 306f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // The size should already be page aligned, now round it up to a power of 2 307f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis // like we did when allocating. 308f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis size = clp2(size); 309f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 310f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis int err = deps.munmap(base, size); 311f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis if (err < 0) { 312f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis err = deps.getErrno(); 3133fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block ALOGW("%s: error unmapping pmem fd: %s", pmemdev, strerror(err)); 314f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return -err; 315f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis } 316f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 317f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis return 0; 318f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 319f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis 320f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie GennisPmemKernelAllocator::Deps::~Deps() 321f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis{ 322f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis BEGIN_FUNC; 323f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis END_FUNC; 324f5a83a9c024dee0617dbc3dab98cd307e8d54665Jamie Gennis} 325