Use memfd blocks for the srbchannel if: - we have memfd support compiled in, and .. - client supports PA protocol version >= 31, and .. - client states that it can handle memfd shared memory Otherwise fall-back to the regular POSIX shm_open() techniques. Signed-off-by: Ahmed S. Darwish <darwish.07 at gmail.com> --- PROTOCOL | 13 ++++++++++++ configure.ac | 2 +- src/pulse/context.c | 29 +++++++++++++++++++++++--- src/pulse/internal.h | 2 ++ src/pulsecore/mem.h | 8 ++++++++ src/pulsecore/protocol-native.c | 45 ++++++++++++++++++++++++++++++++++++----- 6 files changed, 90 insertions(+), 9 deletions(-) diff --git a/PROTOCOL b/PROTOCOL index 3c08fea..1af0908 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -371,6 +371,19 @@ PA_COMMAND_DISABLE_SRBCHANNEL Tells the client to stop listening on the additional SHM ringbuffer channel. Acked by client by sending PA_COMMAND_DISABLE_SRBCHANNEL back. +## v31, implemented by >= 9.0 + +Second most-significant bit of the version tag is now used to flag +memfd SHM support, for both client and server, + +For srbchannels, the server will use memfd communication if: + +- the server has memfd code compiled in, and .. +- client supports protocol version >= 31, and .. +- the client states that it can handle memfd shared memory + +Otherwise, regular posix SHM is used. + #### If you just changed the protocol, read this ## module-tunnel depends on the sink/source/sink-input/source-input protocol ## internals, so if you changed these, you might have broken module-tunnel. diff --git a/configure.ac b/configure.ac index 256a196..6bbee3f 100644 --- a/configure.ac +++ b/configure.ac @@ -40,7 +40,7 @@ AC_SUBST(PA_MINOR, pa_minor) AC_SUBST(PA_MAJORMINOR, pa_major.pa_minor) AC_SUBST(PA_API_VERSION, 12) -AC_SUBST(PA_PROTOCOL_VERSION, 30) +AC_SUBST(PA_PROTOCOL_VERSION, 31) # The stable ABI for client applications, for the version info x:y:z # always will hold y=z diff --git a/src/pulse/context.c b/src/pulse/context.c index 39e1ae8..204c3e5 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -480,6 +480,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t case PA_CONTEXT_AUTHORIZING: { pa_tagstruct *reply; bool shm_on_remote = false; + bool memfd_on_remote = false; if (pa_tagstruct_getu32(t, &c->version) < 0 || !pa_tagstruct_eof(t)) { @@ -498,7 +499,15 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t not. */ if (c->version >= 13) { shm_on_remote = !!(c->version & 0x80000000U); - c->version &= 0x7FFFFFFFU; + + /* Starting with protocol version 31, the second MSB of the version + * tag reflects whether memfd is supported on the other PA end. */ + if (c->version >= 31) + memfd_on_remote = !!(c->version & 0x40000000U); + + /* Reserve the two most-significant _bytes_ of the version tag + * for flags. */ + c->version &= 0x0000FFFFU; } pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION); @@ -524,6 +533,18 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_log_debug("Negotiated SHM: %s", pa_yes_no(c->do_shm)); pa_pstream_enable_shm(c->pstream, c->do_shm); + c->shm_type = PA_MEM_TYPE_PRIVATE; + if (c->do_shm) { + if (c->version >= 31 && memfd_on_remote && pa_memfd_is_locally_supported()) { + pa_pstream_enable_memfd(c->pstream); + c->shm_type = PA_MEM_TYPE_SHARED_MEMFD; + } else + c->shm_type = PA_MEM_TYPE_SHARED_POSIX; + } + + pa_log_debug("Memfd possible: %s", pa_yes_no(pa_memfd_is_locally_supported())); + pa_log_debug("Negotiated SHM type: %s", pa_mem_type_to_string(c->shm_type)); + reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); if (c->version >= 13) { @@ -591,8 +612,10 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_log_debug("SHM possible: %s", pa_yes_no(c->do_shm)); /* Starting with protocol version 13 we use the MSB of the version - * tag for informing the other side if we could do SHM or not */ - pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION | (c->do_shm ? 0x80000000U : 0)); + * tag for informing the other side if we could do SHM or not. + * Starting from version 31, second MSB is used to flag memfd support. */ + pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION | (c->do_shm ? 0x80000000U : 0) | + (pa_memfd_is_locally_supported() ? 0x40000000 : 0)); pa_tagstruct_put_arbitrary(t, cookie, sizeof(cookie)); #ifdef HAVE_CREDS diff --git a/src/pulse/internal.h b/src/pulse/internal.h index eefd181..9c77c94 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -95,6 +95,8 @@ struct pa_context { bool filter_added:1; pa_spawn_api spawn_api; + pa_mem_type_t shm_type; + pa_strlist *server_list; char *server; diff --git a/src/pulsecore/mem.h b/src/pulsecore/mem.h index d0a063c..d0538f4 100644 --- a/src/pulsecore/mem.h +++ b/src/pulsecore/mem.h @@ -56,4 +56,12 @@ static inline const char *pa_mem_type_to_string(pa_mem_type_t type) { pa_assert_not_reached(); } +static inline bool pa_memfd_is_locally_supported() { +#ifdef HAVE_MEMFD + return true; +#else + return false; +#endif +} + #endif diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 58f99c1..1e6d61c 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -48,6 +48,7 @@ #include <pulsecore/core-scache.h> #include <pulsecore/core-subscribe.h> #include <pulsecore/log.h> +#include <pulsecore/mem.h> #include <pulsecore/strlist.h> #include <pulsecore/shared.h> #include <pulsecore/sample-util.h> @@ -2596,11 +2597,12 @@ static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */ } -static void setup_srbchannel(pa_native_connection *c) { +static void setup_srbchannel(pa_native_connection *c, pa_mem_type_t shm_type) { pa_srbchannel_template srbt; pa_srbchannel *srb; pa_memchunk mc; pa_tagstruct *t; + const char *reason; int fdlist[2]; if (!c->options->srbchannel) { @@ -2618,11 +2620,21 @@ static void setup_srbchannel(pa_native_connection *c) { return; } - if (!(c->rw_mempool = pa_mempool_new(PA_MEM_TYPE_SHARED_POSIX, c->protocol->core->shm_size))) { + if (!(c->rw_mempool = pa_mempool_new(shm_type, c->protocol->core->shm_size))) { pa_log_warn("Disabling srbchannel, reason: Failed to allocate shared " "writable memory pool."); return; } + + if (shm_type == PA_MEM_TYPE_SHARED_MEMFD) { + if (pa_pstream_register_memfd_mempool(c->pstream, c->rw_mempool, &reason)) { + pa_log_warn("Disabling srbchannel, reason: Failed to register memfd mempool: %s", reason); + + pa_mempool_free(c->rw_mempool); + c->rw_mempool = NULL; + return; + } + } pa_mempool_set_is_remote_writable(c->rw_mempool, true); srb = pa_srbchannel_new(c->protocol->core->mainloop, c->rw_mempool); @@ -2670,7 +2682,9 @@ static void command_enable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); const void*cookie; + bool memfd_on_remote = false; pa_tagstruct *reply; + pa_mem_type_t shm_type; bool shm_on_remote = false, do_shm; pa_native_connection_assert_ref(c); @@ -2694,7 +2708,15 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta not. */ if (c->version >= 13) { shm_on_remote = !!(c->version & 0x80000000U); - c->version &= 0x7FFFFFFFU; + + /* Starting with protocol version 31, the second MSB of the version + * tag reflects whether memfd is supported on the other PA end. */ + if (c->version >= 31) + memfd_on_remote = !!(c->version & 0x40000000U); + + /* Reserve the two most-significant _bytes_ of the version tag + * for flags. */ + c->version &= 0x0000FFFFU; } pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION); @@ -2781,8 +2803,21 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm)); pa_pstream_enable_shm(c->pstream, do_shm); + shm_type = PA_MEM_TYPE_PRIVATE; + if (do_shm) { + if (c->version >= 31 && memfd_on_remote && pa_memfd_is_locally_supported()) { + shm_type = PA_MEM_TYPE_SHARED_MEMFD; + pa_pstream_enable_memfd(c->pstream); + } else + shm_type = PA_MEM_TYPE_SHARED_POSIX; + + pa_log_debug("Memfd possible: %s", pa_yes_no(pa_memfd_is_locally_supported())); + pa_log_debug("Negotiated SHM type: %s", pa_mem_type_to_string(shm_type)); + } + reply = reply_new(tag); - pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0)); + pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0) | + (pa_memfd_is_locally_supported() ? 0x40000000 : 0)); #ifdef HAVE_CREDS { @@ -2799,7 +2834,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta pa_pstream_send_tagstruct(c->pstream, reply); #endif - setup_srbchannel(c); + setup_srbchannel(c, shm_type); } static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { Regards, -- Darwish http://darwish.chasingpointers.com