root/trunk/libffado/src/libutil/PosixSharedMemory.cpp

Revision 2019, 8.1 kB (checked in by jwoithe, 9 years ago)

From Orcan via trac ticket #344. Writes Orcan:

It is that time of the year that the gcc folks decide to impose the
standards at a higher level. Attached is a trivial patch that will make
libffado compile against new gcc.

Thanks for the patch Orcan.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "PosixSharedMemory.h"
25
26 #include <sys/mman.h>
27 #include <errno.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31
32 namespace Util {
33
34 IMPL_DEBUG_MODULE( PosixSharedMemory, PosixSharedMemory, DEBUG_LEVEL_NORMAL );
35
36 PosixSharedMemory::PosixSharedMemory(std::string name, unsigned int size)
37 : m_name( "/" + name )
38 , m_size( size )
39 , m_owner( false )
40 , m_access( NULL )
41 {
42
43 }
44
45 PosixSharedMemory::~PosixSharedMemory()
46 {
47     debugOutput(DEBUG_LEVEL_VERBOSE,
48                 "(%p, %s) destroy\n",
49                 this, m_name.c_str());
50     Close();
51     if(m_owner) {
52         debugOutput(DEBUG_LEVEL_VERBOSE,
53                     "(%p, %s) unlink\n",
54                     this, m_name.c_str());
55         shm_unlink(m_name.c_str());
56     }
57 }
58
59 bool
60 PosixSharedMemory::Open(enum eDirection d)
61 {
62     debugOutput(DEBUG_LEVEL_VERBOSE,
63                 "(%p, %s) open\n",
64                 this, m_name.c_str());
65     if(m_access != NULL) {
66         debugError("(%p, %s) already attached to segment\n", this, m_name.c_str());
67     }
68
69     int flags=0;
70     switch(d) {
71         case eD_ReadOnly: flags |= O_RDONLY; break;
72         case eD_WriteOnly: flags |= O_WRONLY; break;
73         case eD_ReadWrite: flags |= O_RDWR; break;
74         default:
75             debugError("bad direction\n");
76             return false;
77     }
78
79     // open the shared memory segment
80     int fd = shm_open(m_name.c_str(), flags, S_IRWXU);
81     if (fd < 0) {
82         if (errno != ENOENT) {
83             debugError("(%p, %s) Cannot open shared memory: %s\n",
84                        this, m_name.c_str(), strerror (errno));
85         } else {
86             debugError("(%p, %s) shared memory segment does not exist: %s\n",
87                        this, m_name.c_str(), strerror (errno));
88         }
89         close(fd);
90         return false;
91     }
92
93     // mmap the memory
94     flags=0;
95     switch(d) {
96         case eD_ReadOnly: flags |= PROT_READ; break;
97         case eD_WriteOnly: flags |= PROT_WRITE; break;
98         case eD_ReadWrite: flags |= PROT_READ|PROT_WRITE; break;
99         default:
100             debugError("bad direction\n");
101             shm_unlink(m_name.c_str());
102             return false;
103     }
104
105     m_access = (char*)mmap(0, m_size, flags, MAP_SHARED, fd, 0);
106     if (m_access == MAP_FAILED) {
107         debugError("(%p, %s) Cannot mmap shared memory: %s\n",
108                     this, m_name.c_str(), strerror (errno));
109         close(fd);
110         m_access = NULL;
111         shm_unlink(m_name.c_str());
112         return false;
113     }
114
115     // close the fd
116     close(fd);
117     return true;
118 }
119
120 bool
121 PosixSharedMemory::Create(enum eDirection d)
122 {
123     debugOutput(DEBUG_LEVEL_VERBOSE,
124                 "(%p, %s) create dir: %d, size: %u \n",
125                 this, m_name.c_str(), d, m_size);
126     if(m_access != NULL) {
127         debugError("(%p, %s) already attached to segment\n", this, m_name.c_str());
128     }
129
130     // open the shared memory segment
131     // always create it readwrite, if not, the other side can't map
132     // it correctly, nor can we truncate it to the right length.
133     int fd = shm_open(m_name.c_str(), O_RDWR|O_CREAT, S_IRWXU);
134     if (fd < 0) {
135         debugError("(%p, %s) Cannot open shared memory: %s\n",
136                     this, m_name.c_str(), strerror (errno));
137         close(fd);
138         return false;
139     }
140
141     // set size
142     if (ftruncate (fd, m_size) < 0) {
143         debugError("(%p, %s) Cannot set shared memory size: %s\n",
144                     this, m_name.c_str(), strerror (errno));
145         close(fd);
146         return false;
147     }
148
149     // mmap the memory
150     int flags=0;
151     switch(d) {
152         case eD_ReadOnly: flags |= PROT_READ; break;
153         case eD_WriteOnly: flags |= PROT_WRITE; break;
154         case eD_ReadWrite: flags |= PROT_READ|PROT_WRITE; break;
155         default:
156             debugError("bad direction\n");
157             return false;
158     }
159
160     m_access = (char*)mmap(0, m_size, flags, MAP_SHARED, fd, 0);
161     if (m_access == MAP_FAILED) {
162         debugError("(%p, %s) Cannot mmap shared memory: %s\n",
163                     this, m_name.c_str(), strerror (errno));
164         close(fd);
165         m_access = NULL;
166         return false;
167     }
168
169     // close the fd
170     close(fd);
171
172     m_owner = true;
173     return true;
174 }
175
176 bool
177 PosixSharedMemory::Close()
178 {
179     debugOutput(DEBUG_LEVEL_VERBOSE,
180                 "(%p, %s) close\n",
181                 this, m_name.c_str());
182     if(m_access) {
183         if(munmap(m_access, m_size)) {
184             debugError("(%p, %s) Cannot munmap shared memory: %s\n",
185                        this, m_name.c_str(), strerror (errno));
186             return false;
187         }
188         m_access = NULL;
189     } else {
190         debugOutput(DEBUG_LEVEL_VERBOSE,
191                     "(%p, %s) not open\n",
192                     this, m_name.c_str());
193     }
194     return true;
195 }
196
197 enum PosixSharedMemory::eResult
198 PosixSharedMemory::Write(unsigned int offset, void * buff, unsigned int len)
199 {
200     debugOutput(DEBUG_LEVEL_VERBOSE,
201                 "(%p, %s) write\n",
202                 this, m_name.c_str());
203     if(offset+len <= m_size) {
204         char * addr = m_access + offset;
205         memcpy(addr, buff, len);
206         // if(msync(addr, len, MS_SYNC | MS_INVALIDATE)) {
207         //     debugError("Could not sync written block\n");
208         //     return eR_Error;
209         // }
210         return eR_OK;
211     } else {
212         debugError("Requested block (%u) out of range (%u)\n", offset+len, m_size);
213         return eR_Error;
214     }
215 }
216
217 enum PosixSharedMemory::eResult
218 PosixSharedMemory::Read(unsigned int offset, void * buff, unsigned int len)
219 {
220     debugOutput(DEBUG_LEVEL_VERBOSE,
221                 "(%p, %s) read\n",
222                 this, m_name.c_str());
223     if(offset+len <= m_size) {
224         char * addr = m_access + offset;
225         memcpy(buff, addr, len);
226         return eR_OK;
227     } else {
228         debugError("Requested block (%u) out of range (%u)\n", offset+len, m_size);
229         return eR_Error;
230     }
231 }
232
233 void*
234 PosixSharedMemory::requestBlock(unsigned int offset, unsigned int len)
235 {
236     debugOutput(DEBUG_LEVEL_VERBOSE,
237                 "(%p, %s) getBlock\n",
238                 this, m_name.c_str());
239     if(offset+len <= m_size) {
240         return (void*)(m_access + offset);
241     } else {
242         debugError("Requested block (%u) out of range (%u)\n", offset+len, m_size);
243         return NULL;
244     }
245 }
246
247 void
248 PosixSharedMemory::commitBlock(unsigned int offset, unsigned int len)
249 {
250     debugOutput(DEBUG_LEVEL_VERBOSE,
251                 "(%p, %s) commitBlock\n",
252                 this, m_name.c_str());
253     if(offset+len >= m_size) {
254         debugError("Committed block (%u) out of range (%u)\n", offset+len, m_size);
255     }
256 }
257
258 bool
259 PosixSharedMemory::LockInMemory(bool lock)
260 {
261     debugOutput(DEBUG_LEVEL_VERBOSE,
262                 "(%p, %s) LockInMemory\n",
263                 this, m_name.c_str());
264     if(lock) {
265         if(mlock(m_access, m_size)) {
266             debugError("(%p, %s) Cannot mlock shared memory: %s\n",
267                        this, m_name.c_str(), strerror (errno));
268             return false;
269         } else return true;
270     } else {
271         if(munlock(m_access, m_size)) {
272             debugError("(%p, %s) Cannot munlock shared memory: %s\n",
273                        this, m_name.c_str(), strerror (errno));
274             return false;
275         } else return true;
276     }
277     return false;
278 }
279
280 void
281 PosixSharedMemory::show()
282 {
283     debugOutput(DEBUG_LEVEL_NORMAL, "(%p) PosixSharedMemory %s\n", this, m_name.c_str());
284 }
285
286 } // namespace Util
Note: See TracBrowser for help on using the browser.