blob: 0b9414107ea7cd334b30bbaead9278037373f91f [file] [log] [blame]
Georgios Pinitasb8d5b952019-05-16 14:13:03 +01001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2019 Arm Limited.
Georgios Pinitasb8d5b952019-05-16 14:13:03 +01003 *
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(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
38namespace arm_compute
39{
40namespace utils
41{
42namespace mmap_io
43{
44namespace
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 */
52std::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 */
70size_t get_page_size()
71{
72 return sysconf(_SC_PAGESIZE);
73}
74} // namespace
75
76MMappedFile::MMappedFile()
77 : _filename(), _file_size(0), _map_size(0), _map_offset(0), _fp(nullptr), _data(nullptr)
78{
79}
80
81MMappedFile::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
87MMappedFile::~MMappedFile()
88{
89 release();
90}
91
92bool 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
148void 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
170unsigned char *MMappedFile::data()
171{
172 return static_cast<unsigned char *>(_data);
173}
174
175size_t MMappedFile::file_size() const
176{
177 return _file_size;
178}
179
180size_t MMappedFile::map_size() const
181{
182 return _map_size;
183}
184
185bool 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)