[pulseaudio-discuss] [PATCH 06/11] pulsecore: Extract generic bits from pa_shm into its parent pa_mem
Ahmed S. Darwish
darwish.07 at gmail.com
Sun Sep 20 14:32:27 PDT 2015
pa_shm contains an amount of logic that is not exclusive to POSIX
SHM areas and will need to be reused by memfd memory regions later.
This shared logic includes punching/vacuuming a memory area.
Extract these shared bits out of `pa_shm' and put them in its generic
parent layer `pa_mem'.
Signed-off-by: Ahmed S. Darwish <darwish.07 at gmail.com>
---
src/Makefile.am | 2 +-
src/pulsecore/mem.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++
src/pulsecore/mem.h | 14 +++++++
src/pulsecore/memblock.c | 2 +-
src/pulsecore/privatemem.c | 2 +-
src/pulsecore/shm.c | 64 +++----------------------------
src/pulsecore/shm.h | 5 ---
7 files changed, 116 insertions(+), 67 deletions(-)
create mode 100644 src/pulsecore/mem.c
diff --git a/src/Makefile.am b/src/Makefile.am
index d4a6b5d..0686c8a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -697,7 +697,7 @@ libpulsecommon_ at PA_MAJORMINOR@_la_SOURCES = \
pulsecore/refcnt.h \
pulsecore/srbchannel.c pulsecore/srbchannel.h \
pulsecore/sample-util.c pulsecore/sample-util.h \
- pulsecore/mem.h \
+ pulsecore/mem.h pulsecore/mem.c \
pulsecore/shm.c pulsecore/shm.h \
pulsecore/privatemem.c pulsecore/privatemem.h \
pulsecore/bitset.c pulsecore/bitset.h \
diff --git a/src/pulsecore/mem.c b/src/pulsecore/mem.c
new file mode 100644
index 0000000..a0ca1d8
--- /dev/null
+++ b/src/pulsecore/mem.c
@@ -0,0 +1,94 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2006 Lennart Poettering
+ Copyright 2006 Pierre Ossman <ossman at cendio.se> for Cendio AB
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <pulsecore/mem.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-error.h>
+
+int shared_fd_get_file_size(int fd, size_t *size) {
+ struct stat st;
+
+ if (fstat(fd, &st) < 0) {
+ pa_log("fstat() failed: %s", pa_cstrerror(errno));
+ return -1;
+ }
+
+ if (st.st_size <= 0 ||
+ PA_ALIGN((size_t) st.st_size) != (size_t) st.st_size) {
+ pa_log("Invalid shared memory segment size");
+ return -1;
+ }
+
+ *size = st.st_size;
+ return 0;
+}
+
+void pa_mem_punch_region(struct pa_mem *shm_area, size_t punch_offset, size_t punch_size) {
+ void *ptr;
+ size_t o;
+
+ pa_assert(shm_area->ptr);
+ pa_assert(shm_area->size > 0);
+ pa_assert(punch_offset+punch_size <= shm_area->size);
+
+#ifdef MAP_FAILED
+ pa_assert(shm_area->ptr != MAP_FAILED);
+#endif
+
+ /* You're welcome to implement this as NOOP on systems that don't
+ * support it */
+
+ /* Align the pointer up to multiples of the page size */
+ ptr = (uint8_t*) shm_area->ptr + punch_offset;
+ o = (size_t) ((uint8_t*) ptr - (uint8_t*) PA_PAGE_ALIGN_PTR(ptr));
+
+ if (o > 0) {
+ size_t delta = PA_PAGE_SIZE - o;
+ ptr = (uint8_t*) ptr + delta;
+ punch_size -= delta;
+ }
+
+ /* Align the size down to multiples of page size */
+ punch_size = (punch_size / PA_PAGE_SIZE) * PA_PAGE_SIZE;
+
+#ifdef MADV_REMOVE
+ if (madvise(ptr, punch_size, MADV_REMOVE) >= 0)
+ return;
+#endif
+
+#ifdef MADV_FREE
+ if (madvise(ptr, punch_size, MADV_FREE) >= 0)
+ return;
+#endif
+
+#ifdef MADV_DONTNEED
+ madvise(ptr, punch_size, MADV_DONTNEED);
+#elif defined(POSIX_MADV_DONTNEED)
+ posix_madvise(ptr, punch_size, POSIX_MADV_DONTNEED);
+#endif
+}
diff --git a/src/pulsecore/mem.h b/src/pulsecore/mem.h
index 7390e47..e5a9ec3 100644
--- a/src/pulsecore/mem.h
+++ b/src/pulsecore/mem.h
@@ -20,8 +20,12 @@
License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
***/
+#include <stddef.h>
+
#include <pulse/gccmacro.h>
+#include <pulsecore/macro.h>
+
/* Parent anonymous structure representing a plain memory area and its
* size. Different structures inherit from this, representing different
* memory area types (e.g. Posix SHM, Linux memfds, or private).
@@ -40,4 +44,14 @@ typedef struct pa_mem {
__PA_PARENT_MEM_STRUCT__;
} pa_mem;
+
+/*
+ * Some methods and definitions commonly used by our children
+ */
+
+#define MAX_SHARED_MEM_SIZE (PA_ALIGN(1024*1024*1024))
+
+int shared_fd_get_file_size(int fd, size_t *size);
+void pa_mem_punch_region(pa_mem *shm_area, size_t punch_offset, size_t punch_size);
+
#endif /* SRC_PULSECORE_MEM_H_ */
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index e809f27..ab117d8 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -938,7 +938,7 @@ void pa_mempool_vacuum(pa_mempool *p) {
;
while ((slot = pa_flist_pop(list))) {
- pa_shm_punch(p->mem.ptr, p->mem.size, (size_t) ((uint8_t*) slot - (uint8_t*) p->mem.ptr), p->block_size);
+ pa_mem_punch_region(&p->mem, (size_t) ((uint8_t*) slot - (uint8_t*) p->mem.ptr), p->block_size);
while (pa_flist_push(p->free_slots, slot))
;
diff --git a/src/pulsecore/privatemem.c b/src/pulsecore/privatemem.c
index 7c098d6..017c533 100644
--- a/src/pulsecore/privatemem.c
+++ b/src/pulsecore/privatemem.c
@@ -27,7 +27,7 @@
#include <pulsecore/core-error.h>
#include <pulse/xmalloc.h>
-#define MAX_MEM_SIZE MAX_SHM_SIZE
+#define MAX_MEM_SIZE MAX_SHARED_MEM_SIZE
int pa_privatemem_create(pa_privatemem *m, size_t size) {
pa_assert(m);
diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index 79fde5b..a10c789 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -28,7 +28,6 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
-#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <signal.h>
@@ -106,7 +105,7 @@ int pa_shm_create(pa_shm *m, size_t size, mode_t mode) {
pa_assert(m);
pa_assert(size > 0);
- pa_assert(size <= MAX_SHM_SIZE);
+ pa_assert(size <= MAX_SHARED_MEM_SIZE);
pa_assert(!(mode & ~0777));
pa_assert(mode >= 0600);
@@ -196,58 +195,13 @@ void pa_shm_free(pa_shm *m) {
pa_zero(*m);
}
-void pa_shm_punch(void *shm_start, size_t total_shm_size, size_t punch_offset, size_t punch_size) {
- void *ptr;
- size_t o;
-
- pa_assert(shm_start);
- pa_assert(total_shm_size > 0);
- pa_assert(punch_offset+punch_size <= total_shm_size);
-
-#ifdef MAP_FAILED
- pa_assert(shm_start != MAP_FAILED);
-#endif
-
- /* You're welcome to implement this as NOOP on systems that don't
- * support it */
-
- /* Align the pointer up to multiples of the page size */
- ptr = (uint8_t*) shm_start + punch_offset;
- o = (size_t) ((uint8_t*) ptr - (uint8_t*) PA_PAGE_ALIGN_PTR(ptr));
-
- if (o > 0) {
- size_t delta = PA_PAGE_SIZE - o;
- ptr = (uint8_t*) ptr + delta;
- punch_size -= delta;
- }
-
- /* Align the size down to multiples of page size */
- punch_size = (punch_size / PA_PAGE_SIZE) * PA_PAGE_SIZE;
-
-#ifdef MADV_REMOVE
- if (madvise(ptr, punch_size, MADV_REMOVE) >= 0)
- return;
-#endif
-
-#ifdef MADV_FREE
- if (madvise(ptr, punch_size, MADV_FREE) >= 0)
- return;
-#endif
-
-#ifdef MADV_DONTNEED
- madvise(ptr, punch_size, MADV_DONTNEED);
-#elif defined(POSIX_MADV_DONTNEED)
- posix_madvise(ptr, punch_size, POSIX_MADV_DONTNEED);
-#endif
-}
-
#ifdef HAVE_SHM_OPEN
int pa_shm_attach(pa_shm *m, unsigned id, bool writable) {
char fn[32];
int fd = -1;
int prot;
- struct stat st;
+ size_t size;
pa_assert(m);
@@ -259,19 +213,11 @@ int pa_shm_attach(pa_shm *m, unsigned id, bool writable) {
goto fail;
}
- if (fstat(fd, &st) < 0) {
- pa_log("fstat() failed: %s", pa_cstrerror(errno));
+ if (shared_fd_get_file_size(fd, &size) < 0 ||
+ size > (size_t)(MAX_SHARED_MEM_SIZE+SHM_MARKER_SIZE))
goto fail;
- }
-
- if (st.st_size <= 0 ||
- st.st_size > (off_t) (MAX_SHM_SIZE+SHM_MARKER_SIZE) ||
- PA_ALIGN((size_t) st.st_size) != (size_t) st.st_size) {
- pa_log("Invalid shared memory segment size");
- goto fail;
- }
- m->size = (size_t) st.st_size;
+ m->size = size;
prot = writable ? PROT_READ | PROT_WRITE : PROT_READ;
if ((m->ptr = mmap(NULL, PA_PAGE_ALIGN(m->size), prot, MAP_SHARED, fd, (off_t) 0)) == MAP_FAILED) {
diff --git a/src/pulsecore/shm.h b/src/pulsecore/shm.h
index a8b2546..a1be644 100644
--- a/src/pulsecore/shm.h
+++ b/src/pulsecore/shm.h
@@ -31,15 +31,10 @@ typedef struct pa_shm {
bool do_unlink;
} pa_shm;
-/* 1 GiB at max */
-#define MAX_SHM_SIZE (PA_ALIGN(1024*1024*1024))
-
int pa_shm_create(pa_shm *m, size_t size, mode_t mode);
int pa_shm_attach(pa_shm *m, unsigned id, bool writable);
void pa_shm_free(pa_shm *m);
-void pa_shm_punch(void *shm_start, size_t total_shm_size, size_t punch_offset, size_t punch_size);
-
int pa_shm_cleanup(void);
#endif
--
Darwish
http://darwish.chasingpointers.com
More information about the pulseaudio-discuss
mailing list