[pulseaudio-discuss] [PATCH v2 04/12] pulsecore: Split pa_shm mempool backend into pa_shm and pa_privatemem
David Henningsson
david.henningsson at canonical.com
Fri Feb 12 14:25:19 UTC 2016
On 2016-02-12 01:12, Ahmed S. Darwish wrote:
> Mempools use "pa_shm" for their pools memory allocation. pa_shm is
> then overloaded with two unrelated tasks: either allocating the pool
> using posix SHM or allocating the same pool using private malloc()s.
> The choice depends on system configuration and abilities.
>
> This will not scale when a third pool memory allocation mechanism
> is added (memfds) . Thus, split pa_shm responsibility into:
>
> - pa_shm: responsible for all *shared* memory, posix and memfds
> - pa_privatemem: only responsible for private memory allocations
>
> This way, memfd support can easily be added later.
So, this part I'm still quite hesitant about. It would be easier just to
change pa_shm to look like this, which is similar to I suggested earlier
[1]:
struct pa_shm {
void *ptr;
size_t size;
pa_mem_type_t type;
/* The three fields below are unused if type is PA_MEM_TYPE_PRIVATE */
int fd;
unsigned id;
bool do_unlink; /* Used for PA_MEM_TYPE_SHARED_POSIX only */
}
Instead you did a massive refactoring, add unions inside other unions,
and a privatemem type which contains just one other field, and even has
its own files? Sorry, but I don't see the point in doing all of that.
(Maybe it would make sense in an OOP language, but I don't think it does
in C.)
[1]
https://lists.freedesktop.org/archives/pulseaudio-discuss/2015-September/024482.html
>
> Signed-off-by: Ahmed S. Darwish <darwish.07 at gmail.com>
> ---
> src/Makefile.am | 1 +
> src/pulsecore/mem.h | 9 +++
> src/pulsecore/memblock.c | 68 ++++++++++++---------
> src/pulsecore/privatemem.c | 78 ++++++++++++++++++++++++
> src/pulsecore/privatemem.h | 35 +++++++++++
> src/pulsecore/shm.c | 148 ++++++++++++++++-----------------------------
> src/pulsecore/shm.h | 11 ++--
> 7 files changed, 220 insertions(+), 130 deletions(-)
> create mode 100644 src/pulsecore/privatemem.c
> create mode 100644 src/pulsecore/privatemem.h
>
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 6cb5bd7..f3a62fb 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -701,6 +701,7 @@ libpulsecommon_ at PA_MAJORMINOR@_la_SOURCES = \
> pulsecore/sample-util.c pulsecore/sample-util.h \
> pulsecore/mem.h \
> pulsecore/shm.c pulsecore/shm.h \
> + pulsecore/privatemem.c pulsecore/privatemem.h \
> pulsecore/bitset.c pulsecore/bitset.h \
> pulsecore/socket-client.c pulsecore/socket-client.h \
> pulsecore/socket-server.c pulsecore/socket-server.h \
> diff --git a/src/pulsecore/mem.h b/src/pulsecore/mem.h
> index b6fdba6..d0a063c 100644
> --- a/src/pulsecore/mem.h
> +++ b/src/pulsecore/mem.h
> @@ -24,6 +24,15 @@
>
> #include <pulsecore/macro.h>
>
> +/* Generic interface representing a plain memory area and its size.
> + *
> + * Different memory backends (posix SHM, private, etc.) embed this
> + * structure as their first element for polymorphic access. */
> +typedef struct pa_mem {
> + void *ptr;
> + size_t size;
> +} pa_mem;
> +
> typedef enum pa_mem_type {
> PA_MEM_TYPE_SHARED_POSIX, /* Data is shared and created using POSIX shm_open() */
> PA_MEM_TYPE_SHARED_MEMFD, /* Data is shared and created using Linux memfd_create() */
> diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
> index 3a33a6f..154bd67 100644
> --- a/src/pulsecore/memblock.c
> +++ b/src/pulsecore/memblock.c
> @@ -36,7 +36,9 @@
> #include <pulse/xmalloc.h>
> #include <pulse/def.h>
>
> +#include <pulsecore/mem.h>
> #include <pulsecore/shm.h>
> +#include <pulsecore/privatemem.h>
> #include <pulsecore/log.h>
> #include <pulsecore/hashmap.h>
> #include <pulsecore/semaphore.h>
> @@ -145,8 +147,14 @@ struct pa_mempool {
> pa_semaphore *semaphore;
> pa_mutex *mutex;
>
> - pa_mem_type_t type;
> - pa_shm memory;
> + bool shared;
> + union {
> + pa_mem memory;
> + union {
> + pa_shm shm;
> + pa_privatemem privatemem;
> + } per_type;
> + };
>
> size_t block_size;
> unsigned n_blocks;
> @@ -748,11 +756,9 @@ static void memblock_replace_import(pa_memblock *b) {
>
> pa_mempool *pa_mempool_new(pa_mem_type_t type, size_t size) {
> pa_mempool *p;
> - bool shared;
> char t1[PA_BYTES_SNPRINT_MAX], t2[PA_BYTES_SNPRINT_MAX];
>
> p = pa_xnew0(pa_mempool, 1);
> - p->type = type;
>
> p->block_size = PA_PAGE_ALIGN(PA_MEMPOOL_SLOT_SIZE);
> if (p->block_size < PA_PAGE_SIZE)
> @@ -767,10 +773,13 @@ pa_mempool *pa_mempool_new(pa_mem_type_t type, size_t size) {
> p->n_blocks = 2;
> }
>
> - shared = pa_mem_type_is_shared(type);
> - if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) {
> - pa_xfree(p);
> - return NULL;
> + if (pa_mem_type_is_shared(type)) {
> + p->shared = true;
> + if (pa_shm_create(&p->per_type.shm, type, p->n_blocks * p->block_size, 0700) < 0)
> + goto mem_create_fail;
> + } else {
> + if (pa_privatemem_create(&p->per_type.privatemem, p->n_blocks * p->block_size) < 0)
> + goto mem_create_fail;
> }
>
> pa_log_debug("Using %s memory pool with %u slots of size %s each, total size is %s, maximum usable slot size is %lu",
> @@ -791,6 +800,10 @@ pa_mempool *pa_mempool_new(pa_mem_type_t type, size_t size) {
> p->free_slots = pa_flist_new(p->n_blocks);
>
> return p;
> +
> +mem_create_fail:
> + pa_xfree(p);
> + return NULL;
> }
>
> void pa_mempool_free(pa_mempool *p) {
> @@ -852,15 +865,10 @@ void pa_mempool_free(pa_mempool *p) {
> /* PA_DEBUG_TRAP; */
> }
>
> - switch (p->type) {
> - case PA_MEM_TYPE_SHARED_POSIX:
> - case PA_MEM_TYPE_PRIVATE:
> - pa_shm_free(&p->memory);
> - break;
> - case PA_MEM_TYPE_SHARED_MEMFD:
> - pa_assert_not_reached();
> - break;
> - }
> + if (pa_mempool_is_shared(p))
> + pa_shm_free(&p->per_type.shm);
> + else
> + pa_privatemem_free(&p->per_type.privatemem);
>
> pa_mutex_free(p->mutex);
> pa_semaphore_free(p->semaphore);
> @@ -896,7 +904,7 @@ void pa_mempool_vacuum(pa_mempool *p) {
> ;
>
> while ((slot = pa_flist_pop(list))) {
> - pa_shm_punch(&p->memory, (size_t) ((uint8_t*) slot - (uint8_t*) p->memory.ptr), p->block_size);
> + pa_shm_punch(&p->per_type.shm, (size_t) ((uint8_t*) slot - (uint8_t*) p->memory.ptr), p->block_size);
>
> while (pa_flist_push(p->free_slots, slot))
> ;
> @@ -909,10 +917,10 @@ void pa_mempool_vacuum(pa_mempool *p) {
> int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) {
> pa_assert(p);
>
> - if (!p->memory.shared)
> + if (!pa_mempool_is_shared(p))
> return -1;
>
> - *id = p->memory.id;
> + *id = p->per_type.shm.id;
>
> return 0;
> }
> @@ -921,7 +929,7 @@ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) {
> bool pa_mempool_is_shared(pa_mempool *p) {
> pa_assert(p);
>
> - return p->memory.shared;
> + return p->shared;
> }
>
> /* For receiving blocks from other nodes */
> @@ -964,7 +972,7 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id, bo
>
> seg->writable = writable;
> seg->import = i;
> - seg->trap = pa_memtrap_add(seg->memory.ptr, seg->memory.size);
> + seg->trap = pa_memtrap_add(seg->memory.mem.ptr, seg->memory.mem.size);
>
> pa_hashmap_put(i->segments, PA_UINT32_TO_PTR(seg->memory.id), seg);
> return seg;
> @@ -1044,7 +1052,7 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i
> goto finish;
> }
>
> - if (offset+size > seg->memory.size)
> + if (offset+size > seg->memory.mem.size)
> goto finish;
>
> if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
> @@ -1055,7 +1063,7 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i
> b->type = PA_MEMBLOCK_IMPORTED;
> b->read_only = !writable;
> b->is_silence = false;
> - pa_atomic_ptr_store(&b->data, (uint8_t*) seg->memory.ptr + offset);
> + pa_atomic_ptr_store(&b->data, (uint8_t*) seg->memory.mem.ptr + offset);
> b->length = size;
> pa_atomic_store(&b->n_acquired, 0);
> pa_atomic_store(&b->please_signal, 0);
> @@ -1103,7 +1111,7 @@ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void
> pa_assert(p);
> pa_assert(cb);
>
> - if (!p->memory.shared)
> + if (!pa_mempool_is_shared(p))
> return NULL;
>
> e = pa_xnew(pa_memexport, 1);
> @@ -1231,7 +1239,7 @@ static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *b) {
>
> /* Self-locked */
> int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32_t *shm_id, size_t *offset, size_t * size) {
> - pa_shm *memory;
> + pa_shm *memory;
> struct memexport_slot *slot;
> void *data;
>
> @@ -1274,14 +1282,14 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32
> } else {
> pa_assert(b->type == PA_MEMBLOCK_POOL || b->type == PA_MEMBLOCK_POOL_EXTERNAL);
> pa_assert(b->pool);
> - memory = &b->pool->memory;
> + memory = &b->pool->per_type.shm;
> }
>
> - pa_assert(data >= memory->ptr);
> - pa_assert((uint8_t*) data + b->length <= (uint8_t*) memory->ptr + memory->size);
> + pa_assert(data >= memory->mem.ptr);
> + pa_assert((uint8_t*) data + b->length <= (uint8_t*) memory->mem.ptr + memory->mem.size);
>
> *shm_id = memory->id;
> - *offset = (size_t) ((uint8_t*) data - (uint8_t*) memory->ptr);
> + *offset = (size_t) ((uint8_t*) data - (uint8_t*) memory->mem.ptr);
> *size = b->length;
>
> pa_memblock_release(b);
> diff --git a/src/pulsecore/privatemem.c b/src/pulsecore/privatemem.c
> new file mode 100644
> index 0000000..99df8c7
> --- /dev/null
> +++ b/src/pulsecore/privatemem.c
> @@ -0,0 +1,78 @@
> +/***
> + 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 <pulsecore/shm.h>
> +#include <pulsecore/privatemem.h>
> +#include <pulsecore/core-error.h>
> +#include <pulse/xmalloc.h>
> +
> +#define MAX_MEM_SIZE PA_MAX_SHM_SIZE
> +
> +int pa_privatemem_create(pa_privatemem *m, size_t size) {
> + pa_assert(m);
> + pa_assert(size > 0);
> + pa_assert(size <= MAX_MEM_SIZE);
> +
> + /* Round up to make it page aligned */
> + size = PA_PAGE_ALIGN(size);
> +
> + m->mem.size = size;
> +
> +#ifdef MAP_ANONYMOUS
> + if ((m->mem.ptr = mmap(NULL, m->mem.size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (off_t) 0)) == MAP_FAILED) {
> + pa_log("mmap() failed: %s", pa_cstrerror(errno));
> + goto fail;
> + }
> +#elif defined(HAVE_POSIX_MEMALIGN)
> + {
> + int r;
> +
> + if ((r = posix_memalign(&m->mem.ptr, PA_PAGE_SIZE, size)) < 0) {
> + pa_log("posix_memalign() failed: %s", pa_cstrerror(r));
> + goto fail;
> + }
> + }
> +#else
> + m->mem.ptr = pa_xmalloc(m->mem.size);
> +#endif
> +
> + return 0;
> +fail:
> + return -1;
> +}
> +
> +void pa_privatemem_free(pa_privatemem *m) {
> + pa_assert(m);
> + pa_assert(m->mem.ptr);
> + pa_assert(m->mem.size > 0);
> +
> +#ifdef MAP_ANONYMOUS
> + if (munmap(m->mem.ptr, m->mem.size) < 0)
> + pa_log("munmap() failed: %s", pa_cstrerror(errno));
> +#elif defined(HAVE_POSIX_MEMALIGN)
> + free(m->mem.ptr);
> +#else
> + pa_xfree(m->mem.ptr);
> +#endif
> +}
> diff --git a/src/pulsecore/privatemem.h b/src/pulsecore/privatemem.h
> new file mode 100644
> index 0000000..9240ce0
> --- /dev/null
> +++ b/src/pulsecore/privatemem.h
> @@ -0,0 +1,35 @@
> +#ifndef foopulseprivatememhfoo
> +#define foopulseprivatememhfoo
> +
> +/***
> + This file is part of PulseAudio.
> +
> + Copyright 2015 Ahmed S. Darwish <darwish.07 at gmail.com>
> +
> + 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/>.
> +***/
> +
> +#include <pulsecore/mem.h>
> +
> +/* Private memory for the mempools. This is usually used if posix SHM
> + * or Linux memfds are not available, or if we're explicitly asked
> + * not to use any form of shared memory. */
> +typedef struct pa_privatemem {
> + pa_mem mem; /* Parent; must be first */
> +} pa_privatemem;
> +
> +int pa_privatemem_create(pa_privatemem *m, size_t size);
> +void pa_privatemem_free(pa_privatemem *m);
> +
> +#endif
> diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
> index d613168..4c0ecf1 100644
> --- a/src/pulsecore/shm.c
> +++ b/src/pulsecore/shm.c
> @@ -58,9 +58,6 @@
> #define MADV_REMOVE 9
> #endif
>
> -/* 1 GiB at max */
> -#define MAX_SHM_SIZE (PA_ALIGN(1024*1024*1024))
> -
> #ifdef __linux__
> /* On Linux we know that the shared memory blocks are files in
> * /dev/shm. We can use that information to list all blocks and
> @@ -100,15 +97,17 @@ static char *segment_name(char *fn, size_t l, unsigned id) {
> }
> #endif
>
> -int pa_shm_create_rw(pa_shm *m, size_t size, bool shared, mode_t mode) {
> +int pa_shm_create(pa_shm *m, pa_mem_type_t type, size_t size, mode_t mode) {
> #ifdef HAVE_SHM_OPEN
> char fn[32];
> int fd = -1;
> #endif
> + struct shm_marker *marker;
>
> pa_assert(m);
> + pa_assert(pa_mem_type_is_shared(type));
> pa_assert(size > 0);
> - pa_assert(size <= MAX_SHM_SIZE);
> + pa_assert(size <= PA_MAX_SHM_SIZE);
> pa_assert(!(mode & ~0777));
> pa_assert(mode >= 0600);
>
> @@ -119,72 +118,42 @@ int pa_shm_create_rw(pa_shm *m, size_t size, bool shared, mode_t mode) {
> /* Round up to make it page aligned */
> size = PA_PAGE_ALIGN(size);
>
> - if (!shared) {
> - m->id = 0;
> - m->size = size;
> -
> -#ifdef MAP_ANONYMOUS
> - if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (off_t) 0)) == MAP_FAILED) {
> - pa_log("mmap() failed: %s", pa_cstrerror(errno));
> - goto fail;
> - }
> -#elif defined(HAVE_POSIX_MEMALIGN)
> - {
> - int r;
> -
> - if ((r = posix_memalign(&m->ptr, PA_PAGE_SIZE, size)) < 0) {
> - pa_log("posix_memalign() failed: %s", pa_cstrerror(r));
> - goto fail;
> - }
> - }
> -#else
> - m->ptr = pa_xmalloc(m->size);
> -#endif
> -
> - m->do_unlink = false;
> -
> - } else {
> #ifdef HAVE_SHM_OPEN
> - struct shm_marker *marker;
> + pa_random(&m->id, sizeof(m->id));
> + segment_name(fn, sizeof(fn), m->id);
>
> - pa_random(&m->id, sizeof(m->id));
> - segment_name(fn, sizeof(fn), m->id);
> + if ((fd = shm_open(fn, O_RDWR|O_CREAT|O_EXCL, mode)) < 0) {
> + pa_log("shm_open() failed: %s", pa_cstrerror(errno));
> + goto fail;
> + }
>
> - if ((fd = shm_open(fn, O_RDWR|O_CREAT|O_EXCL, mode)) < 0) {
> - pa_log("shm_open() failed: %s", pa_cstrerror(errno));
> - goto fail;
> - }
> + m->mem.size = size + SHM_MARKER_SIZE;
>
> - m->size = size + SHM_MARKER_SIZE;
> -
> - if (ftruncate(fd, (off_t) m->size) < 0) {
> - pa_log("ftruncate() failed: %s", pa_cstrerror(errno));
> - goto fail;
> - }
> + if (ftruncate(fd, (off_t) m->mem.size) < 0) {
> + pa_log("ftruncate() failed: %s", pa_cstrerror(errno));
> + goto fail;
> + }
>
> #ifndef MAP_NORESERVE
> #define MAP_NORESERVE 0
> #endif
>
> - if ((m->ptr = mmap(NULL, PA_PAGE_ALIGN(m->size), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd, (off_t) 0)) == MAP_FAILED) {
> - pa_log("mmap() failed: %s", pa_cstrerror(errno));
> - goto fail;
> - }
> -
> - /* We store our PID at the end of the shm block, so that we
> - * can check for dead shm segments later */
> - marker = (struct shm_marker*) ((uint8_t*) m->ptr + m->size - SHM_MARKER_SIZE);
> - pa_atomic_store(&marker->pid, (int) getpid());
> - pa_atomic_store(&marker->marker, SHM_MARKER);
> -
> - pa_assert_se(pa_close(fd) == 0);
> - m->do_unlink = true;
> -#else
> + if ((m->mem.ptr = mmap(NULL, PA_PAGE_ALIGN(m->mem.size), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd, (off_t) 0)) == MAP_FAILED) {
> + pa_log("mmap() failed: %s", pa_cstrerror(errno));
> goto fail;
> -#endif
> }
>
> - m->shared = shared;
> + /* We store our PID at the end of the shm block, so that we
> + * can check for dead shm segments later */
> + marker = (struct shm_marker*) ((uint8_t*) m->mem.ptr + m->mem.size - SHM_MARKER_SIZE);
> + pa_atomic_store(&marker->pid, (int) getpid());
> + pa_atomic_store(&marker->marker, SHM_MARKER);
> +
> + pa_assert_se(pa_close(fd) == 0);
> + m->do_unlink = true;
> +#else
> + goto fail;
> +#endif
>
> return 0;
>
> @@ -202,40 +171,28 @@ fail:
>
> void pa_shm_free(pa_shm *m) {
> pa_assert(m);
> - pa_assert(m->ptr);
> - pa_assert(m->size > 0);
> + pa_assert(m->mem.ptr);
> + pa_assert(m->mem.size > 0);
>
> #ifdef MAP_FAILED
> - pa_assert(m->ptr != MAP_FAILED);
> + pa_assert(m->mem.ptr != MAP_FAILED);
> #endif
>
> - if (!m->shared) {
> -#ifdef MAP_ANONYMOUS
> - if (munmap(m->ptr, m->size) < 0)
> - pa_log("munmap() failed: %s", pa_cstrerror(errno));
> -#elif defined(HAVE_POSIX_MEMALIGN)
> - free(m->ptr);
> -#else
> - pa_xfree(m->ptr);
> -#endif
> - } else {
> #ifdef HAVE_SHM_OPEN
> - if (munmap(m->ptr, PA_PAGE_ALIGN(m->size)) < 0)
> - pa_log("munmap() failed: %s", pa_cstrerror(errno));
> + if (munmap(m->mem.ptr, PA_PAGE_ALIGN(m->mem.size)) < 0)
> + pa_log("munmap() failed: %s", pa_cstrerror(errno));
>
> - if (m->do_unlink) {
> - char fn[32];
> + if (m->do_unlink) {
> + char fn[32];
>
> - segment_name(fn, sizeof(fn), m->id);
> -
> - if (shm_unlink(fn) < 0)
> - pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno));
> - }
> -#else
> - /* We shouldn't be here without shm support */
> - pa_assert_not_reached();
> -#endif
> + segment_name(fn, sizeof(fn), m->id);
> + if (shm_unlink(fn) < 0)
> + pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno));
> }
> +#else
> + /* We shouldn't be here without shm support */
> + pa_assert_not_reached();
> +#endif
>
> pa_zero(*m);
> }
> @@ -245,19 +202,19 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) {
> size_t o;
>
> pa_assert(m);
> - pa_assert(m->ptr);
> - pa_assert(m->size > 0);
> - pa_assert(offset+size <= m->size);
> + pa_assert(m->mem.ptr);
> + pa_assert(m->mem.size > 0);
> + pa_assert(offset+size <= m->mem.size);
>
> #ifdef MAP_FAILED
> - pa_assert(m->ptr != MAP_FAILED);
> + pa_assert(m->mem.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*) m->ptr + offset;
> + ptr = (uint8_t*) m->mem.ptr + offset;
> o = (size_t) ((uint8_t*) ptr - (uint8_t*) PA_PAGE_ALIGN_PTR(ptr));
>
> if (o > 0) {
> @@ -310,22 +267,21 @@ static int shm_attach(pa_shm *m, unsigned id, bool writable, bool for_cleanup) {
> }
>
> if (st.st_size <= 0 ||
> - st.st_size > (off_t) (MAX_SHM_SIZE+SHM_MARKER_SIZE) ||
> + st.st_size > (off_t) (PA_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->mem.size = (size_t) st.st_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) {
> + if ((m->mem.ptr = mmap(NULL, PA_PAGE_ALIGN(m->mem.size), prot, MAP_SHARED, fd, (off_t) 0)) == MAP_FAILED) {
> pa_log("mmap() failed: %s", pa_cstrerror(errno));
> goto fail;
> }
>
> m->do_unlink = false;
> - m->shared = true;
>
> pa_assert_se(pa_close(fd) == 0);
>
> @@ -382,12 +338,12 @@ int pa_shm_cleanup(void) {
> if (shm_attach(&seg, id, false, true) < 0)
> continue;
>
> - if (seg.size < SHM_MARKER_SIZE) {
> + if (seg.mem.size < SHM_MARKER_SIZE) {
> pa_shm_free(&seg);
> continue;
> }
>
> - m = (struct shm_marker*) ((uint8_t*) seg.ptr + seg.size - SHM_MARKER_SIZE);
> + m = (struct shm_marker*) ((uint8_t*) seg.mem.ptr + seg.mem.size - SHM_MARKER_SIZE);
>
> if (pa_atomic_load(&m->marker) != SHM_MARKER) {
> pa_shm_free(&seg);
> diff --git a/src/pulsecore/shm.h b/src/pulsecore/shm.h
> index d438961..887f516 100644
> --- a/src/pulsecore/shm.h
> +++ b/src/pulsecore/shm.h
> @@ -23,16 +23,19 @@
> #include <sys/types.h>
>
> #include <pulsecore/macro.h>
> +#include <pulsecore/mem.h>
> +
> +/* 1 GiB at max */
> +#define PA_MAX_SHM_SIZE (PA_ALIGN(1024*1024*1024))
>
> typedef struct pa_shm {
> + pa_mem mem; /* Parent; must be first */
> + pa_mem_type_t type;
> unsigned id;
> - void *ptr;
> - size_t size;
> bool do_unlink:1;
> - bool shared:1;
> } pa_shm;
>
> -int pa_shm_create_rw(pa_shm *m, size_t size, bool shared, mode_t mode);
> +int pa_shm_create(pa_shm *m, pa_mem_type_t type, size_t size, mode_t mode);
> int pa_shm_attach(pa_shm *m, unsigned id, bool writable);
>
> void pa_shm_punch(pa_shm *m, size_t offset, size_t size);
>
> Regards,
>
--
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic
More information about the pulseaudio-discuss
mailing list