xref: /aosp_15_r20/external/ComputeLibrary/src/core/utils/misc/MMappedFile.cpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2019, 2022 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #if !defined(_WIN64) && !defined(BARE_METAL)
25 
26 #include "arm_compute/core/utils/misc/MMappedFile.h"
27 
28 #include <cstdio>
29 #include <cstring>
30 #include <tuple>
31 
32 #include <fcntl.h>
33 #include <sys/mman.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <unistd.h>
37 
38 namespace arm_compute
39 {
40 namespace utils
41 {
42 namespace mmap_io
43 {
44 namespace
45 {
46 /** File size accessor
47  *
48  * @param[in] filename File to extract its size
49  *
50  * @return A pair of size and status.
51  */
get_file_size(const std::string & filename)52 std::pair<size_t, bool> get_file_size(const std::string &filename)
53 {
54     struct stat st; // NOLINT
55     memset(&st, 0, sizeof(struct stat));
56     if(stat(filename.c_str(), &st) == 0)
57     {
58         return std::make_pair(st.st_size, true);
59     }
60     else
61     {
62         return std::make_pair(0, false);
63     }
64 }
65 
66 /** Get OS page size
67  *
68  * @return Page size
69  */
get_page_size()70 size_t get_page_size()
71 {
72     return sysconf(_SC_PAGESIZE);
73 }
74 } // namespace
75 
MMappedFile()76 MMappedFile::MMappedFile()
77     : _filename(), _file_size(0), _map_size(0), _map_offset(0), _fp(nullptr), _data(nullptr)
78 {
79 }
80 
MMappedFile(std::string filename,size_t size,size_t offset)81 MMappedFile::MMappedFile(std::string filename, size_t size, size_t offset)
82     : _filename(std::move(filename)), _file_size(0), _map_size(size), _map_offset(offset), _fp(nullptr), _data(nullptr)
83 {
84     map(_filename, _map_size, _map_offset);
85 }
86 
~MMappedFile()87 MMappedFile::~MMappedFile()
88 {
89     release();
90 }
91 
map(const std::string & filename,size_t size,size_t offset)92 bool MMappedFile::map(const std::string &filename, size_t size, size_t offset)
93 {
94     // Check if file is mapped
95     if(is_mapped())
96     {
97         return false;
98     }
99 
100     // Open file
101     _fp = fopen(filename.c_str(), "a+be");
102     if(_fp == nullptr)
103     {
104         return false;
105     }
106 
107     // Extract file descriptor
108     int  fd     = fileno(_fp);
109     bool status = fd >= 0;
110     if(status)
111     {
112         // Get file size
113         std::tie(_file_size, status) = get_file_size(_filename);
114 
115         if(status)
116         {
117             // Map all file from offset if map size is 0
118             _map_size   = (size == 0) ? _file_size : size;
119             _map_offset = offset;
120 
121             // Check offset mapping
122             if((_map_offset > _file_size) || (_map_offset % get_page_size() != 0))
123             {
124                 status = false;
125             }
126             else
127             {
128                 // Truncate to file size
129                 if(_map_offset + _map_size > _file_size)
130                 {
131                     _map_size = _file_size - _map_offset;
132                 }
133 
134                 // Perform mapping
135                 _data = ::mmap(nullptr, _map_size, PROT_WRITE, MAP_SHARED, fd, _map_offset);
136             }
137         }
138     }
139 
140     if(!status)
141     {
142         fclose(_fp);
143     }
144 
145     return status;
146 }
147 
release()148 void MMappedFile::release()
149 {
150     // Unmap file
151     if(_data != nullptr)
152     {
153         ::munmap(_data, _file_size);
154         _data = nullptr;
155     }
156 
157     // Close file
158     if(_fp != nullptr)
159     {
160         fclose(_fp);
161         _fp = nullptr;
162     }
163 
164     // Clear variables
165     _file_size  = 0;
166     _map_size   = 0;
167     _map_offset = 0;
168 }
169 
data()170 unsigned char *MMappedFile::data()
171 {
172     return static_cast<unsigned char *>(_data);
173 }
174 
file_size() const175 size_t MMappedFile::file_size() const
176 {
177     return _file_size;
178 }
179 
map_size() const180 size_t MMappedFile::map_size() const
181 {
182     return _map_size;
183 }
184 
is_mapped() const185 bool MMappedFile::is_mapped() const
186 {
187     return _data != nullptr;
188 }
189 } // namespace mmap_io
190 } // namespace utils
191 } // namespace arm_compute
192 #endif // !defined(BARE_METAL)
193