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