]>
code.delx.au - pulseaudio/blob - src/pulsecore/shm.c
444d4010e13a476f30f8839f2927c28e0ce7b4b8
4 This file is part of PulseAudio.
6 Copyright 2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as
11 published by the Free Software Foundation; either version 2.1 of the
12 License, or (at your option) any later version.
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
38 #ifdef HAVE_SYS_MMAN_H
42 #include <pulsecore/core-error.h>
43 #include <pulsecore/log.h>
44 #include <pulsecore/random.h>
45 #include <pulse/xmalloc.h>
49 #if defined(__linux__) && !defined(MADV_REMOVE)
53 #define MAX_SHM_SIZE (1024*1024*20)
55 static char *segment_name(char *fn
, size_t l
, unsigned id
) {
56 snprintf(fn
, l
, "/pulse-shm-%u", id
);
60 int pa_shm_create_rw(pa_shm
*m
, size_t size
, int shared
, mode_t mode
) {
66 assert(size
< MAX_SHM_SIZE
);
74 if ((m
->ptr
= mmap(NULL
, m
->size
, PROT_READ
|PROT_WRITE
, MAP_ANONYMOUS
|MAP_PRIVATE
, -1, 0)) == MAP_FAILED
) {
75 pa_log("mmap() failed: %s", pa_cstrerror(errno
));
78 #elif defined(HAVE_POSIX_MEMALIGN)
82 if ((r
= posix_memalign(&m
->ptr
, sysconf(_SC_PAGESIZE
), size
)) < 0) {
83 pa_log("posix_memalign() failed: %s", pa_cstrerror(r
));
88 m
->ptr
= pa_xmalloc(m
->size
);
95 pa_random(&m
->id
, sizeof(m
->id
));
96 segment_name(fn
, sizeof(fn
), m
->id
);
98 if ((fd
= shm_open(fn
, O_RDWR
|O_CREAT
|O_EXCL
, mode
& 0444)) < 0) {
99 pa_log("shm_open() failed: %s", pa_cstrerror(errno
));
103 if (ftruncate(fd
, m
->size
= size
) < 0) {
104 pa_log("ftruncate() failed: %s", pa_cstrerror(errno
));
108 if ((m
->ptr
= mmap(NULL
, m
->size
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, 0)) == MAP_FAILED
) {
109 pa_log("mmap() failed: %s", pa_cstrerror(errno
));
136 void pa_shm_free(pa_shm
*m
) {
142 assert(m
->ptr
!= MAP_FAILED
);
147 if (munmap(m
->ptr
, m
->size
) < 0)
148 pa_log("munmap() failed: %s", pa_cstrerror(errno
));
149 #elif defined(HAVE_POSIX_MEMALIGN)
156 if (munmap(m
->ptr
, m
->size
) < 0)
157 pa_log("munmap() failed: %s", pa_cstrerror(errno
));
162 segment_name(fn
, sizeof(fn
), m
->id
);
164 if (shm_unlink(fn
) < 0)
165 pa_log(" shm_unlink(%s) failed: %s", fn
, pa_cstrerror(errno
));
168 /* We shouldn't be here without shm support */
173 memset(m
, 0, sizeof(*m
));
176 void pa_shm_punch(pa_shm
*m
, size_t offset
, size_t size
) {
182 assert(offset
+size
<= m
->size
);
185 assert(m
->ptr
!= MAP_FAILED
);
188 /* You're welcome to implement this as NOOP on systems that don't
191 ptr
= (uint8_t*) m
->ptr
+ offset
;
195 /* On Linux ptr must be page aligned */
196 long psz
= sysconf(_SC_PAGESIZE
);
199 o
= ((unsigned long) ptr
) - ((((unsigned long) ptr
)/psz
) * psz
);
202 ptr
= (uint8_t*) ptr
+ (psz
- o
);
209 if (madvise(ptr
, size
, MADV_REMOVE
) >= 0)
214 if (madvise(ptr
, size
, MADV_FREE
) >= 0)
219 madvise(ptr
, size
, MADV_DONTNEED
);
225 int pa_shm_attach_ro(pa_shm
*m
, unsigned id
) {
232 segment_name(fn
, sizeof(fn
), m
->id
= id
);
234 if ((fd
= shm_open(fn
, O_RDONLY
, 0)) < 0) {
235 pa_log("shm_open() failed: %s", pa_cstrerror(errno
));
239 if (fstat(fd
, &st
) < 0) {
240 pa_log("fstat() failed: %s", pa_cstrerror(errno
));
244 if (st
.st_size
<= 0 || st
.st_size
> MAX_SHM_SIZE
) {
245 pa_log("Invalid shared memory segment size");
249 m
->size
= st
.st_size
;
251 if ((m
->ptr
= mmap(NULL
, m
->size
, PROT_READ
, MAP_SHARED
, fd
, 0)) == MAP_FAILED
) {
252 pa_log("mmap() failed: %s", pa_cstrerror(errno
));
270 #else /* HAVE_SHM_OPEN */
272 int pa_shm_attach_ro(pa_shm
*m
, unsigned id
) {
276 #endif /* HAVE_SHM_OPEN */