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