]>
code.delx.au - pulseaudio/blob - src/pulsecore/shm.c
4 This file is part of PulseAudio.
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
35 #ifdef HAVE_SYS_MMAN_H
39 #include <pulsecore/core-error.h>
40 #include <pulsecore/log.h>
41 #include <pulsecore/random.h>
42 #include <pulse/xmalloc.h>
46 #if defined(__linux__) && !defined(MADV_REMOVE)
50 #define MAX_SHM_SIZE (1024*1024*20)
52 static char *segment_name(char *fn
, size_t l
, unsigned id
) {
53 snprintf(fn
, l
, "/pulse-shm-%u", id
);
59 int pa_shm_create_rw(pa_shm
*m
, size_t size
, int shared
, mode_t mode
) {
65 assert(size
< MAX_SHM_SIZE
);
73 if ((m
->ptr
= mmap(NULL
, m
->size
, PROT_READ
|PROT_WRITE
, MAP_ANONYMOUS
|MAP_PRIVATE
, -1, 0)) == MAP_FAILED
) {
74 pa_log("mmap() failed: %s", pa_cstrerror(errno
));
77 #elif defined(HAVE_POSIX_MEMALIGN)
81 if ((r
= posix_memalign(&m
->ptr
, sysconf(_SC_PAGESIZE
), size
)) < 0) {
82 pa_log("posix_memalign() failed: %s", pa_cstrerror(r
));
87 m
->ptr
= pa_xmalloc(m
->size
);
93 pa_random(&m
->id
, sizeof(m
->id
));
94 segment_name(fn
, sizeof(fn
), m
->id
);
96 if ((fd
= shm_open(fn
, O_RDWR
|O_CREAT
|O_EXCL
, mode
& 0444)) < 0) {
97 pa_log("shm_open() failed: %s", pa_cstrerror(errno
));
101 if (ftruncate(fd
, m
->size
= size
) < 0) {
102 pa_log("ftruncate() failed: %s", pa_cstrerror(errno
));
106 if ((m
->ptr
= mmap(NULL
, m
->size
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, 0)) == MAP_FAILED
) {
107 pa_log("mmap() failed: %s", pa_cstrerror(errno
));
129 void pa_shm_free(pa_shm
*m
) {
133 assert(m
->ptr
&& m
->ptr
!= MAP_FAILED
);
136 #if !defined(MAP_ANONYMOUS) && defined(HAVE_POSIX_MEMALIGN)
140 #elif !defined(MAP_ANONYMOUS)
146 if (munmap(m
->ptr
, m
->size
) < 0)
147 pa_log("munmap() failed: %s", pa_cstrerror(errno
));
150 segment_name(fn
, sizeof(fn
), m
->id
);
152 if (shm_unlink(fn
) < 0)
153 pa_log(__FILE__
":shm_unlink(%s) failed: %s", fn
, pa_cstrerror(errno
));
156 memset(m
, 0, sizeof(*m
));
159 void pa_shm_punch(pa_shm
*m
, size_t offset
, size_t size
) {
163 assert(m
->ptr
&& m
->ptr
!= MAP_FAILED
);
165 assert(offset
< m
->size
);
166 assert(offset
+size
< m
->size
);
168 /* You're welcome to implement this as NOOP on systems that don't
171 ptr
= (uint8_t*) m
->ptr
+ offset
;
175 /* On Linux ptr must be page aligned */
176 long psz
= sysconf(_SC_PAGESIZE
);
179 o
= ((unsigned long) ptr
) - ((((unsigned long) ptr
)/psz
) * psz
);
182 ptr
= (uint8_t*) ptr
+ (psz
- o
);
189 if (madvise(ptr
, size
, MADV_REMOVE
) >= 0)
194 if (madvise(ptr
, size
, MADV_FREE
) >= 0)
199 madvise(ptr
, size
, MADV_DONTNEED
);
203 int pa_shm_attach_ro(pa_shm
*m
, unsigned id
) {
210 segment_name(fn
, sizeof(fn
), m
->id
= id
);
212 if ((fd
= shm_open(fn
, O_RDONLY
, 0)) < 0) {
213 pa_log("shm_open() failed: %s", pa_cstrerror(errno
));
217 if (fstat(fd
, &st
) < 0) {
218 pa_log("fstat() failed: %s", pa_cstrerror(errno
));
222 if (st
.st_size
<= 0 || st
.st_size
> MAX_SHM_SIZE
) {
223 pa_log("Invalid shared memory segment size");
227 m
->size
= st
.st_size
;
229 if ((m
->ptr
= mmap(NULL
, m
->size
, PROT_READ
, MAP_SHARED
, fd
, 0)) == MAP_FAILED
) {
230 pa_log("mmap() failed: %s", pa_cstrerror(errno
));
248 #else /* HAVE_SHM_OPEN */
250 int pa_shm_create_rw(pa_shm
*m
, size_t size
, int shared
, mode_t mode
) {
254 void pa_shm_free(pa_shm
*m
) {
257 void pa_shm_punch(pa_shm
*m
, size_t offset
, size_t size
) {
260 int pa_shm_attach_ro(pa_shm
*m
, unsigned id
) {
264 #endif /* HAVE_SHM_OPEN */