xref: /aosp_15_r20/external/libtextclassifier/native/utils/memory/mmap.h (revision 993b0882672172b81d12fad7a7ac0c3e5c824a12)
1*993b0882SAndroid Build Coastguard Worker /*
2*993b0882SAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*993b0882SAndroid Build Coastguard Worker  *
4*993b0882SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*993b0882SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*993b0882SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*993b0882SAndroid Build Coastguard Worker  *
8*993b0882SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*993b0882SAndroid Build Coastguard Worker  *
10*993b0882SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*993b0882SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*993b0882SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*993b0882SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*993b0882SAndroid Build Coastguard Worker  * limitations under the License.
15*993b0882SAndroid Build Coastguard Worker  */
16*993b0882SAndroid Build Coastguard Worker 
17*993b0882SAndroid Build Coastguard Worker #ifndef LIBTEXTCLASSIFIER_UTILS_MEMORY_MMAP_H_
18*993b0882SAndroid Build Coastguard Worker #define LIBTEXTCLASSIFIER_UTILS_MEMORY_MMAP_H_
19*993b0882SAndroid Build Coastguard Worker 
20*993b0882SAndroid Build Coastguard Worker #include <stddef.h>
21*993b0882SAndroid Build Coastguard Worker 
22*993b0882SAndroid Build Coastguard Worker #include <string>
23*993b0882SAndroid Build Coastguard Worker 
24*993b0882SAndroid Build Coastguard Worker #include "utils/base/integral_types.h"
25*993b0882SAndroid Build Coastguard Worker #include "utils/strings/stringpiece.h"
26*993b0882SAndroid Build Coastguard Worker 
27*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
28*993b0882SAndroid Build Coastguard Worker 
29*993b0882SAndroid Build Coastguard Worker // Handle for a memory area where a file has been mmapped.
30*993b0882SAndroid Build Coastguard Worker //
31*993b0882SAndroid Build Coastguard Worker // Similar to a pointer: you "allocate" it using MmapFile(filename) and "delete"
32*993b0882SAndroid Build Coastguard Worker // it using Unmap().  Just like a pointer, it is passed around by value (see
33*993b0882SAndroid Build Coastguard Worker // signature of MmapFile and Unmap; fortunately, it's a small class, so there
34*993b0882SAndroid Build Coastguard Worker // shouldn't be any significant performance penalty) and its usage is not
35*993b0882SAndroid Build Coastguard Worker // necessarily scoped (that's why the destructor is not performing the unmap).
36*993b0882SAndroid Build Coastguard Worker //
37*993b0882SAndroid Build Coastguard Worker // Note: on program termination, each still unmapped file is automatically
38*993b0882SAndroid Build Coastguard Worker // unmapped.  Hence, it is not an error if you don't call Unmap() (provided you
39*993b0882SAndroid Build Coastguard Worker // are ok keeping that file in memory the whole time).
40*993b0882SAndroid Build Coastguard Worker class MmapHandle {
41*993b0882SAndroid Build Coastguard Worker  public:
42*993b0882SAndroid Build Coastguard Worker   MmapHandle(void *start, size_t num_bytes, void *unmap_addr = nullptr)
start_(start)43*993b0882SAndroid Build Coastguard Worker       : start_(start), num_bytes_(num_bytes), unmap_addr_(unmap_addr) {}
44*993b0882SAndroid Build Coastguard Worker 
45*993b0882SAndroid Build Coastguard Worker   // Returns start address for the memory area where a file has been mmapped.
start()46*993b0882SAndroid Build Coastguard Worker   void *start() const { return start_; }
47*993b0882SAndroid Build Coastguard Worker 
48*993b0882SAndroid Build Coastguard Worker   // Returns address to use for munmap call. If unmap_addr was not specified
49*993b0882SAndroid Build Coastguard Worker   // the start address is used.
unmap_addr()50*993b0882SAndroid Build Coastguard Worker   void *unmap_addr() const {
51*993b0882SAndroid Build Coastguard Worker     if (unmap_addr_ != nullptr) {
52*993b0882SAndroid Build Coastguard Worker       return unmap_addr_;
53*993b0882SAndroid Build Coastguard Worker     } else {
54*993b0882SAndroid Build Coastguard Worker       return start_;
55*993b0882SAndroid Build Coastguard Worker     }
56*993b0882SAndroid Build Coastguard Worker   }
57*993b0882SAndroid Build Coastguard Worker 
58*993b0882SAndroid Build Coastguard Worker   // Returns number of bytes of the memory area from start().
num_bytes()59*993b0882SAndroid Build Coastguard Worker   size_t num_bytes() const { return num_bytes_; }
60*993b0882SAndroid Build Coastguard Worker 
61*993b0882SAndroid Build Coastguard Worker   // Shortcut to simplify checking success of MmapFile().  See usage example
62*993b0882SAndroid Build Coastguard Worker   // from the doc of that function.
ok()63*993b0882SAndroid Build Coastguard Worker   bool ok() const { return start() != nullptr; }
64*993b0882SAndroid Build Coastguard Worker 
65*993b0882SAndroid Build Coastguard Worker   // Returns a StringPiece pointing to the same underlying bytes.
to_stringpiece()66*993b0882SAndroid Build Coastguard Worker   StringPiece to_stringpiece() const {
67*993b0882SAndroid Build Coastguard Worker     return StringPiece(reinterpret_cast<char *>(start_), num_bytes_);
68*993b0882SAndroid Build Coastguard Worker   }
69*993b0882SAndroid Build Coastguard Worker 
70*993b0882SAndroid Build Coastguard Worker  private:
71*993b0882SAndroid Build Coastguard Worker   // See doc for start().  Not owned.
72*993b0882SAndroid Build Coastguard Worker   void *const start_;
73*993b0882SAndroid Build Coastguard Worker 
74*993b0882SAndroid Build Coastguard Worker   // See doc for num_bytes().
75*993b0882SAndroid Build Coastguard Worker   const size_t num_bytes_;
76*993b0882SAndroid Build Coastguard Worker 
77*993b0882SAndroid Build Coastguard Worker   // Address to use for unmapping.
78*993b0882SAndroid Build Coastguard Worker   void *const unmap_addr_;
79*993b0882SAndroid Build Coastguard Worker };
80*993b0882SAndroid Build Coastguard Worker 
81*993b0882SAndroid Build Coastguard Worker // Maps the full content of a file in memory (using mmap).
82*993b0882SAndroid Build Coastguard Worker //
83*993b0882SAndroid Build Coastguard Worker // When done using the file content, one can unmap using Unmap().  Otherwise,
84*993b0882SAndroid Build Coastguard Worker // all mapped files are unmapped when the program terminates.
85*993b0882SAndroid Build Coastguard Worker //
86*993b0882SAndroid Build Coastguard Worker // Sample usage:
87*993b0882SAndroid Build Coastguard Worker //
88*993b0882SAndroid Build Coastguard Worker // MmapHandle mmap_handle = MmapFile(filename);
89*993b0882SAndroid Build Coastguard Worker // TC3_DCHECK(mmap_handle.ok()) << "Unable to mmap " << filename;
90*993b0882SAndroid Build Coastguard Worker //
91*993b0882SAndroid Build Coastguard Worker // ... use data from addresses
92*993b0882SAndroid Build Coastguard Worker // ... [mmap_handle.start, mmap_handle.start + mmap_handle.num_bytes)
93*993b0882SAndroid Build Coastguard Worker //
94*993b0882SAndroid Build Coastguard Worker // Unmap(mmap_handle);  // Unmap logs errors internally.
95*993b0882SAndroid Build Coastguard Worker //
96*993b0882SAndroid Build Coastguard Worker // Note: one can read *and* write the num_bytes bytes from start, but those
97*993b0882SAndroid Build Coastguard Worker // writes are not propagated to the underlying file, nor to other processes that
98*993b0882SAndroid Build Coastguard Worker // may have mmapped that file (all changes are local to current process).
99*993b0882SAndroid Build Coastguard Worker MmapHandle MmapFile(const std::string &filename);
100*993b0882SAndroid Build Coastguard Worker 
101*993b0882SAndroid Build Coastguard Worker // Like MmapFile(const std::string &filename), but uses a file descriptor.
102*993b0882SAndroid Build Coastguard Worker MmapHandle MmapFile(int fd);
103*993b0882SAndroid Build Coastguard Worker 
104*993b0882SAndroid Build Coastguard Worker // Maps a segment of a file to memory. File is given by a file descriptor, and
105*993b0882SAndroid Build Coastguard Worker // offset (relative to the beginning of the file) and size specify the segment
106*993b0882SAndroid Build Coastguard Worker // to be mapped. NOTE: Internally, we align the offset for the call to mmap
107*993b0882SAndroid Build Coastguard Worker // system call to be a multiple of page size, so offset does NOT have to be a
108*993b0882SAndroid Build Coastguard Worker // multiply of the page size.
109*993b0882SAndroid Build Coastguard Worker MmapHandle MmapFile(int fd, int64 segment_offset, int64 segment_size);
110*993b0882SAndroid Build Coastguard Worker 
111*993b0882SAndroid Build Coastguard Worker // Unmaps a file mapped using MmapFile.  Returns true on success, false
112*993b0882SAndroid Build Coastguard Worker // otherwise.
113*993b0882SAndroid Build Coastguard Worker bool Unmap(MmapHandle mmap_handle);
114*993b0882SAndroid Build Coastguard Worker 
115*993b0882SAndroid Build Coastguard Worker // Scoped mmapping of a file.  Mmaps a file on construction, unmaps it on
116*993b0882SAndroid Build Coastguard Worker // destruction.
117*993b0882SAndroid Build Coastguard Worker class ScopedMmap {
118*993b0882SAndroid Build Coastguard Worker  public:
ScopedMmap(const std::string & filename)119*993b0882SAndroid Build Coastguard Worker   explicit ScopedMmap(const std::string &filename)
120*993b0882SAndroid Build Coastguard Worker       : handle_(MmapFile(filename)) {}
121*993b0882SAndroid Build Coastguard Worker 
ScopedMmap(int fd)122*993b0882SAndroid Build Coastguard Worker   explicit ScopedMmap(int fd) : handle_(MmapFile(fd)) {}
123*993b0882SAndroid Build Coastguard Worker 
ScopedMmap(int fd,int segment_offset,int segment_size)124*993b0882SAndroid Build Coastguard Worker   ScopedMmap(int fd, int segment_offset, int segment_size)
125*993b0882SAndroid Build Coastguard Worker       : handle_(MmapFile(fd, segment_offset, segment_size)) {}
126*993b0882SAndroid Build Coastguard Worker 
~ScopedMmap()127*993b0882SAndroid Build Coastguard Worker   ~ScopedMmap() {
128*993b0882SAndroid Build Coastguard Worker     if (handle_.ok()) {
129*993b0882SAndroid Build Coastguard Worker       Unmap(handle_);
130*993b0882SAndroid Build Coastguard Worker     }
131*993b0882SAndroid Build Coastguard Worker   }
132*993b0882SAndroid Build Coastguard Worker 
handle()133*993b0882SAndroid Build Coastguard Worker   const MmapHandle &handle() const { return handle_; }
134*993b0882SAndroid Build Coastguard Worker 
135*993b0882SAndroid Build Coastguard Worker  private:
136*993b0882SAndroid Build Coastguard Worker   MmapHandle handle_;
137*993b0882SAndroid Build Coastguard Worker };
138*993b0882SAndroid Build Coastguard Worker 
139*993b0882SAndroid Build Coastguard Worker }  // namespace libtextclassifier3
140*993b0882SAndroid Build Coastguard Worker 
141*993b0882SAndroid Build Coastguard Worker #endif  // LIBTEXTCLASSIFIER_UTILS_MEMORY_MMAP_H_
142