Line data Source code
1 : // DUNE DAQ modification notice:
2 : // This file has been modified from the original ATLAS system source for the DUNE DAQ project.
3 : // Fork baseline commit: system-00-00-20 (2020-09-25).
4 : // Renamed since fork: yes (from src/MapFile.cxx to src/MapFile.cpp).
5 :
6 : /*
7 : * MapFile.cxx
8 : * ers
9 : *
10 : * Created by Matthias Wiesmann on 07.01.05.
11 : * Copyright 2005 CERN. All rights reserved.
12 : *
13 : */
14 :
15 : #include <iostream>
16 : #include <sys/mman.h>
17 : #include <sys/types.h>
18 : #include <unistd.h>
19 :
20 : #include "okssystem/Descriptor.hpp"
21 : #include "okssystem/MapFile.hpp"
22 : #include "okssystem/exceptions.hpp"
23 :
24 : #include "ers/Assertion.hpp"
25 :
26 : /** Builds a memory mapped file.
27 : * \param name the path of the file to map.
28 : * \param size the size of the region to memory map - should be a multiple of the pagesize.
29 : * \param offset the offset in the file - should be a multiple of pagesize.
30 : * \param read_mode should the map be read from the file.
31 : * \param write_mode should the map be writable.
32 : * \param permissions the permissions associated with the file
33 : */
34 :
35 0 : OksSystem::MapFile::MapFile(const std::string& name, size_t s, size_t o, bool read_mode, bool write_mode, mode_t perm)
36 0 : : File(name)
37 : {
38 0 : ERS_PRECONDITION((read_mode || write_mode));
39 0 : const int page_size = getpagesize();
40 0 : ERS_PRECONDITION((s % page_size) == 0);
41 0 : ERS_PRECONDITION((o % page_size) == 0);
42 0 : (void)page_size; // to suppress warning when asserts are disabled
43 0 : m_map_read = read_mode;
44 0 : m_map_write = write_mode;
45 0 : m_map_permission = perm;
46 0 : m_map_size = s;
47 0 : m_map_offset = o;
48 0 : m_map_address = 0;
49 0 : m_map_descriptor = 0;
50 0 : m_is_mapped = false;
51 0 : } // MapFile
52 :
53 : /** Destructor - the file should be unmapped before destruction.
54 : */
55 :
56 0 : OksSystem::MapFile::~MapFile()
57 : {
58 0 : if (m_map_descriptor != 0) {
59 0 : close_fd();
60 : } // file descriptor open
61 0 : } // ~MapFile
62 :
63 : /** Opens the file descriptor associated with the memory map.
64 : * \exception OpenFail if the \c open okssystem call fails
65 : */
66 :
67 : void
68 0 : OksSystem::MapFile::open_fd()
69 : {
70 0 : const int flags = OksSystem::Descriptor::flags(m_map_read, m_map_write);
71 0 : m_map_descriptor = new OksSystem::Descriptor(this, flags, m_map_permission);
72 0 : } // open_fd
73 :
74 : /** Closes the file descriptor associated with the memory map.
75 : * \exception CloseFail if the \c close okssystem call fails
76 : */
77 :
78 : void
79 0 : OksSystem::MapFile::close_fd()
80 : {
81 0 : m_map_descriptor->close();
82 0 : delete (m_map_descriptor);
83 0 : m_map_descriptor = 0;
84 0 : } // close_fd
85 :
86 : /** Internal method - does the actual memory mapping.
87 : * \exception MMapFail if the \c mmap operation succeeded
88 : * \exception Precondition if the file descriptor is not valid.
89 : */
90 :
91 : void
92 0 : OksSystem::MapFile::map_mem()
93 : {
94 0 : ERS_PRECONDITION(m_map_descriptor);
95 0 : int prot = 0;
96 0 : int flags = MAP_FILE | MAP_SHARED;
97 0 : if (m_map_read) {
98 0 : prot |= PROT_READ;
99 : }
100 0 : if (m_map_write) {
101 0 : prot |= PROT_WRITE;
102 : }
103 0 : m_map_address = ::mmap(0, m_map_size, prot, flags, *m_map_descriptor, m_map_offset);
104 0 : if (m_map_address == MAP_FAILED || m_map_address == 0) {
105 0 : m_is_mapped = false;
106 0 : std::string message = "on file " + this->full_name();
107 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "mmap", message.c_str());
108 0 : } /* map_failed */ else {
109 0 : m_is_mapped = true;
110 : }
111 0 : } // map_mem
112 :
113 : /** Internal method - does the actual memory unmapping.
114 : * \exception MUnmapFail if the \c munmap operation fails.
115 : */
116 :
117 : void
118 0 : OksSystem::MapFile::unmap_mem()
119 : {
120 0 : ERS_PRECONDITION(m_map_address != 0);
121 0 : const int status = munmap(m_map_address, m_map_size);
122 0 : if (status < 0) {
123 0 : m_is_mapped = true;
124 0 : std::string message = "on file " + this->full_name();
125 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "munmap", message.c_str());
126 0 : } else {
127 0 : m_is_mapped = false;
128 : }
129 0 : } // unmap_mem
130 :
131 : /** Creates a zero filled file with correct length
132 : */
133 :
134 : void
135 0 : OksSystem::MapFile::zero() const
136 : {
137 0 : ERS_ASSERT(m_map_write == true);
138 0 : const int flags = OksSystem::Descriptor::flags(false, true);
139 0 : OksSystem::Descriptor fd(this, flags, m_map_permission);
140 0 : const int page_size = ::getpagesize();
141 0 : const int page_num = (m_map_size + m_map_offset) / page_size;
142 0 : void* buffer = calloc(1, page_size);
143 0 : for (int i = 0; i < page_num; i++) {
144 0 : fd.write(buffer, page_size);
145 : } // for
146 0 : free(buffer);
147 0 : fd.close();
148 0 : } // zero
149 :
150 : /** Maps the file into memory.
151 : * This is done first by opening the file descriptor for the file, then doing the actual map.
152 : * \exception OpenFail error while opening the file
153 : * \exception MMapFail error while mapping the file
154 : */
155 :
156 : void
157 0 : OksSystem::MapFile::map()
158 : {
159 0 : open_fd();
160 0 : map_mem();
161 0 : } // map
162 :
163 : /** Unmaps the file from memory
164 : * This is done first by unmapping the file, then closing the file-descriptor.
165 : * \exception CloseFail error while closing the file.
166 : * \exception MUnmapFail error while unmapping the file.
167 : */
168 :
169 : void
170 0 : OksSystem::MapFile::unmap()
171 : {
172 0 : unmap_mem();
173 0 : close_fd();
174 0 : } // unmap
175 :
176 : bool
177 0 : OksSystem::MapFile::is_loaded() const throw()
178 : {
179 0 : return (m_map_address != 0);
180 : } // is_loaded
181 :
182 : /** Gives the actual address of the map in memory.
183 : * If the file is not yet mapped, this will be 0.
184 : * \return point to the start address of the mapped file in memory.
185 : */
186 :
187 : void*
188 0 : OksSystem::MapFile::address() const throw()
189 : {
190 0 : return m_map_address;
191 : } // address
192 :
193 : /** Gives the actual size of the map in memory.
194 : * \return the size of the memory region
195 : */
196 :
197 : size_t
198 0 : OksSystem::MapFile::memory_size() const throw()
199 : {
200 0 : return m_map_size;
201 : } // memory_size
202 :
203 : /** Returns if the file is mapped or not in memory */
204 :
205 : bool
206 0 : OksSystem::MapFile::is_mapped() const
207 : {
208 0 : return m_is_mapped;
209 : }
210 :
211 : OksSystem::Descriptor*
212 0 : OksSystem::MapFile::fd() const throw()
213 : {
214 0 : return m_map_descriptor;
215 : }
|