[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