[pulseaudio-discuss] [PATCH v2 10/12] srbchannel: Use memfd transport by default; pump protocol version

Ahmed S. Darwish darwish.07 at gmail.com
Fri Feb 12 00:19:55 UTC 2016


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


More information about the pulseaudio-discuss mailing list