]>
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
36 #include <pulsecore/core-error.h>
37 #include <pulsecore/log.h>
38 #include <pulsecore/random.h>
39 #include <pulse/xmalloc.h>
43 #if defined(__linux__) && !defined(MADV_REMOVE)
47 #define MAX_SHM_SIZE (1024*1024*20)
49 static char *segment_name(char *fn
, size_t l
, unsigned id
) {
50 snprintf(fn
, l
, "/pulse-shm-%u", id
);
54 int pa_shm_create_rw(pa_shm
*m
, size_t size
, int shared
, mode_t mode
) {
60 assert(size
< MAX_SHM_SIZE
);
68 if ((m
->ptr
= mmap(NULL
, m
->size
, PROT_READ
|PROT_WRITE
, MAP_ANONYMOUS
|MAP_PRIVATE
, -1, 0)) == MAP_FAILED
) {
69 pa_log("mmap() failed: %s", pa_cstrerror(errno
));
72 #elif defined(HAVE_POSIX_MEMALIGN)
76 if ((r
= posix_memalign(&m
->ptr
, sysconf(_SC_PAGESIZE
), size
)) < 0) {
77 pa_log("posix_memalign() failed: %s", pa_cstrerror(r
));
82 m
->ptr
= pa_xmalloc(m
->size
);
88 pa_random(&m
->id
, sizeof(m
->id
));
89 segment_name(fn
, sizeof(fn
), m
->id
);
91 if ((fd
= shm_open(fn
, O_RDWR
|O_CREAT
|O_EXCL
, mode
& 0444)) < 0) {
92 pa_log("shm_open() failed: %s", pa_cstrerror(errno
));
96 if (ftruncate(fd
, m
->size
= size
) < 0) {
97 pa_log("ftruncate() failed: %s", pa_cstrerror(errno
));
101 if ((m
->ptr
= mmap(NULL
, m
->size
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, 0)) == MAP_FAILED
) {
102 pa_log("mmap() failed: %s", pa_cstrerror(errno
));
124 void pa_shm_free(pa_shm
*m
) {
128 assert(m
->ptr
&& m
->ptr
!= MAP_FAILED
);
131 #if !defined(MAP_ANONYMOUS) && defined(HAVE_POSIX_MEMALIGN)
135 #elif !defined(MAP_ANONYMOUS)
141 if (munmap(m
->ptr
, m
->size
) < 0)
142 pa_log("munmap() failed: %s", pa_cstrerror(errno
));
145 segment_name(fn
, sizeof(fn
), m
->id
);
147 if (shm_unlink(fn
) < 0)
148 pa_log(__FILE__
":shm_unlink(%s) failed: %s", fn
, pa_cstrerror(errno
));
151 memset(m
, 0, sizeof(*m
));
154 void pa_shm_punch(pa_shm
*m
, size_t offset
, size_t size
) {
158 assert(m
->ptr
&& m
->ptr
!= MAP_FAILED
);
160 assert(offset
< m
->size
);
161 assert(offset
+size
< m
->size
);
163 /* You're welcome to implement this as NOOP on systems that don't
166 ptr
= (uint8_t*) m
->ptr
+ offset
;
170 /* On Linux ptr must be page aligned */
171 long psz
= sysconf(_SC_PAGESIZE
);
174 o
= ((unsigned long) ptr
) - ((((unsigned long) ptr
)/psz
) * psz
);
177 ptr
= (uint8_t*) ptr
+ (psz
- o
);
184 if (madvise(ptr
, size
, MADV_REMOVE
) >= 0)
189 if (madvise(ptr
, size
, MADV_FREE
) >= 0)
194 madvise(ptr
, size
, MADV_DONTNEED
);
198 int pa_shm_attach_ro(pa_shm
*m
, unsigned id
) {
205 segment_name(fn
, sizeof(fn
), m
->id
= id
);
207 if ((fd
= shm_open(fn
, O_RDONLY
, 0)) < 0) {
208 pa_log("shm_open() failed: %s", pa_cstrerror(errno
));
212 if (fstat(fd
, &st
) < 0) {
213 pa_log("fstat() failed: %s", pa_cstrerror(errno
));
217 if (st
.st_size
<= 0 || st
.st_size
> MAX_SHM_SIZE
) {
218 pa_log("Invalid shared memory segment size");
222 m
->size
= st
.st_size
;
224 if ((m
->ptr
= mmap(NULL
, m
->size
, PROT_READ
, MAP_SHARED
, fd
, 0)) == MAP_FAILED
) {
225 pa_log("mmap() failed: %s", pa_cstrerror(errno
));