ProfileDataContainer.cpp revision 34781b253083703502a7874df3619196bc7106cd
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "ProfileDataContainer.h"
18
19#include <log/log.h>
20#include <cutils/ashmem.h>
21
22#include <sys/mman.h>
23
24namespace android {
25namespace uirenderer {
26
27void ProfileDataContainer::freeData() {
28    if (mIsMapped) {
29        munmap(mData, sizeof(ProfileData));
30    } else {
31        delete mData;
32    }
33    mIsMapped = false;
34    mData = nullptr;
35}
36
37void ProfileDataContainer::rotateStorage() {
38    // If we are mapped we want to stop using the ashmem backend and switch to malloc
39    // We are expecting a switchStorageToAshmem call to follow this, but it's not guaranteed
40    // If we aren't sitting on top of ashmem then just do a reset() as it's functionally
41    // equivalent do a free, malloc, reset.
42    if (mIsMapped) {
43        freeData();
44        mData = new ProfileData;
45    }
46    mData->reset();
47}
48
49void ProfileDataContainer::switchStorageToAshmem(int ashmemfd) {
50    int regionSize = ashmem_get_size_region(ashmemfd);
51    if (regionSize < 0) {
52        int err = errno;
53        ALOGW("Failed to get ashmem region size from fd %d, err %d %s", ashmemfd, err, strerror(err));
54        return;
55    }
56    if (regionSize < static_cast<int>(sizeof(ProfileData))) {
57        ALOGW("Ashmem region is too small! Received %d, required %u",
58                regionSize, static_cast<unsigned int>(sizeof(ProfileData)));
59        return;
60    }
61    ProfileData* newData = reinterpret_cast<ProfileData*>(
62            mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE,
63                    MAP_SHARED, ashmemfd, 0));
64    if (newData == MAP_FAILED) {
65        int err = errno;
66        ALOGW("Failed to move profile data to ashmem fd %d, error = %d",
67                ashmemfd, err);
68        return;
69    }
70
71    newData->mergeWith(*mData);
72    freeData();
73    mData = newData;
74    mIsMapped = true;
75}
76
77} /* namespace uirenderer */
78} /* namespace android */