18b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet/*
28b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet * Copyright (C) 2017 The Android Open Source Project
38b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet *
48b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet * Licensed under the Apache License, Version 2.0 (the "License");
58b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet * you may not use this file except in compliance with the License.
68b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet * You may obtain a copy of the License at
78b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet *
88b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet *      http://www.apache.org/licenses/LICENSE-2.0
98b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet *
108b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet * Unless required by applicable law or agreed to in writing, software
118b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet * distributed under the License is distributed on an "AS IS" BASIS,
128b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet * See the License for the specific language governing permissions and
148b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet * limitations under the License.
158b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet */
168b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet
178b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet#define LOG_TAG "Memory"
188b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet
198b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet#include "Memory.h"
208b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet
218b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet#include "HalInterfaces.h"
228b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet#include "Utils.h"
238b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet
248b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletnamespace android {
258b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletnamespace nn {
268b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet
278b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletint Memory::create(uint32_t size) {
288b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    mHidlMemory = allocateSharedMemory(size);
298b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    mMemory = mapMemory(mHidlMemory);
308b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    if (mMemory == nullptr) {
318b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet        LOG(ERROR) << "Memory::create failed";
32a144106df8f9b82251a5e584b1b083fb39d33b88Przemyslaw Szczepaniak        return ANEURALNETWORKS_OUT_OF_MEMORY;
338b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    }
348b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    return ANEURALNETWORKS_NO_ERROR;
358b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet}
368b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet
37e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouilletbool Memory::validateSize(uint32_t offset, uint32_t length) const {
38e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (offset + length > mHidlMemory.size()) {
39e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        LOG(ERROR) << "Request size larger than the memory size.";
40e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return false;
41e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    } else {
42e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return true;
43e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
44e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet}
45e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet
46e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc BrouilletMemoryFd::~MemoryFd() {
47fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross    // Unmap the memory.
48fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross    if (mMapping) {
49fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross        munmap(mMapping, mHidlMemory.size());
50fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross    }
51e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    // Delete the native_handle.
52e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (mHandle) {
53e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        int fd = mHandle->data[0];
54e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        if (fd != -1) {
55e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet            close(fd);
56e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        }
57e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        native_handle_delete(mHandle);
58e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
59e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet}
60e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet
61e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouilletint MemoryFd::set(size_t size, int prot, int fd, size_t offset) {
62e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (fd < 0) {
63e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        LOG(ERROR) << "ANeuralNetworksMemory_createFromFd invalid fd " << fd;
64e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return ANEURALNETWORKS_UNEXPECTED_NULL;
65e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
66e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (size == 0 || fd < 0) {
67e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        LOG(ERROR) << "Invalid size or fd";
68e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
69e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
70e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    int dupfd = dup(fd);
71e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (dupfd == -1) {
72e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        LOG(ERROR) << "Failed to dup the fd";
73e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return ANEURALNETWORKS_UNEXPECTED_NULL;
74e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
75e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet
76fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross    if (mMapping) {
77fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross        if (munmap(mMapping, mHidlMemory.size()) != 0) {
78fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross            LOG(ERROR) << "Failed to remove the existing mapping";
79fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross            // This is not actually fatal.
80fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross        }
81fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross        mMapping = nullptr;
82fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross    }
83e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (mHandle) {
84e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        native_handle_delete(mHandle);
85e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
86e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    mHandle = native_handle_create(1, 3);
87e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (mHandle == nullptr) {
88e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        LOG(ERROR) << "Failed to create native_handle";
89e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return ANEURALNETWORKS_UNEXPECTED_NULL;
90e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
91e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    mHandle->data[0] = dupfd;
92e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    mHandle->data[1] = prot;
93e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    mHandle->data[2] = (int32_t)(uint32_t)(offset & 0xffffffff);
94e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet#if defined(__LP64__)
95e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    mHandle->data[3] = (int32_t)(uint32_t)(offset >> 32);
96e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet#else
97e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    mHandle->data[3] = 0;
98e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet#endif
99e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    mHidlMemory = hidl_memory("mmap_fd", mHandle, size);
100e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    return ANEURALNETWORKS_NO_ERROR;
101e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet}
102e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet
103e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouilletint MemoryFd::getPointer(uint8_t** buffer) const {
104fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross    if (mMapping) {
105fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross        *buffer = mMapping;
106fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross        return ANEURALNETWORKS_NO_ERROR;
107fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross    }
108fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross
109e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (mHandle == nullptr) {
110e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        LOG(ERROR) << "Memory not initialized";
111e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return ANEURALNETWORKS_UNEXPECTED_NULL;
112e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
113e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet
114e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    int fd = mHandle->data[0];
115e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    int prot = mHandle->data[1];
116e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    size_t offset = getSizeFromInts(mHandle->data[2], mHandle->data[3]);
117e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    void* data = mmap(nullptr, mHidlMemory.size(), prot, MAP_SHARED, fd, offset);
118e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    if (data == MAP_FAILED) {
11906b5a0a85abe10b618a3a5ed023ac5c74678647eDavid Gross        LOG(ERROR) << "MemoryFd::getPointer(): Can't mmap the file descriptor.";
120e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return ANEURALNETWORKS_UNMAPPABLE;
121e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    } else {
122fc43986520df188b3d099f3582c65c1f55c5f35eDavid Gross        mMapping = *buffer = static_cast<uint8_t*>(data);
123e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet        return ANEURALNETWORKS_NO_ERROR;
124e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet    }
125e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet}
126e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet
1278b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouilletuint32_t MemoryTracker::add(const Memory* memory) {
12864031fa26110e6d57896bfdbe1cd58e69cde3dbbMiao Wang    VLOG(MODEL) << __func__ << "(" << SHOW_IF_DEBUG(memory) << ")";
1298b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    // See if we already have this memory. If so,
1308b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    // return its index.
1318b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    auto i = mKnown.find(memory);
1328b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    if (i != mKnown.end()) {
1338b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet        return i->second;
1348b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    }
1351da8fed77c5c296afa18f754ec3616e7f02a4cfdJean-Luc Brouillet    VLOG(MODEL) << "It's new";
1368b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    // It's a new one.  Save it an assign an index to it.
1378b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    size_t next = mKnown.size();
1388b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    if (next > 0xFFFFFFFF) {
1398b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet        LOG(ERROR) << "ANeuralNetworks more than 2^32 memories.";
1408b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet        return ANEURALNETWORKS_BAD_DATA;
1418b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    }
1428b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    uint32_t idx = static_cast<uint32_t>(next);
1438b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    mKnown[memory] = idx;
1448b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    mMemories.push_back(memory);
1458b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet    return idx;
1468b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet}
1478b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet
1488b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet} // namespace nn
1498b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet} // namespace android
150