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