Commit b1d47d60 authored by Ahmed S. Darwish's avatar Ahmed S. Darwish Committed by Arun Raghavan

client audio: Support memfd transport

Now that all layers in the stack support memfd blocks, add memfd
pools support for client context and audio playback data.

Use such memfd pools by default only if the server signals memfd
support in its connection negotiations.

Also add ability for clients to force-disable memfd transport
through the `enable-memfd=' client configuration option.
Signed-off-by: default avatarAhmed S. Darwish <darwish.07@gmail.com>
parent a831e455
......@@ -102,6 +102,14 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
<option>
<p><opt>enable-shm=</opt> Enable data transfer via POSIX
or memfd shared memory. Takes a boolean argument, defaults to
<opt>yes</opt>. If set to <opt>no</opt>, communication with
the server will be exclusively done through data-copy over
sockets.</p>
</option>
<option>
<p><opt>enable-memfd=</opt>. Enable data transfer via memfd
shared memory. Takes a boolean argument, defaults to
<opt>yes</opt>.</p>
</option>
......
......@@ -141,6 +141,7 @@ void pa_client_conf_load(pa_client_conf *c, bool load_from_x11, bool load_from_e
{ "cookie-file", pa_config_parse_string, &c->cookie_file_from_client_conf, NULL },
{ "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL },
{ "enable-shm", pa_config_parse_not_bool, &c->disable_shm, NULL },
{ "enable-memfd", pa_config_parse_not_bool, &c->disable_memfd, NULL },
{ "shm-size-bytes", pa_config_parse_size, &c->shm_size, NULL },
{ "auto-connect-localhost", pa_config_parse_bool, &c->auto_connect_localhost, NULL },
{ "auto-connect-display", pa_config_parse_bool, &c->auto_connect_display, NULL },
......
......@@ -37,7 +37,7 @@ typedef struct pa_client_conf {
bool cookie_from_x11_valid;
char *cookie_file_from_application;
char *cookie_file_from_client_conf;
bool autospawn, disable_shm, auto_connect_localhost, auto_connect_display;
bool autospawn, disable_shm, disable_memfd, auto_connect_localhost, auto_connect_display;
size_t shm_size;
} pa_client_conf;
......
......@@ -173,7 +173,12 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
c->srb_template.readfd = -1;
c->srb_template.writefd = -1;
type = !c->conf->disable_shm ? PA_MEM_TYPE_SHARED_POSIX : PA_MEM_TYPE_PRIVATE;
c->memfd_on_local = (!c->conf->disable_memfd && pa_memfd_is_locally_supported());
type = (c->conf->disable_shm) ? PA_MEM_TYPE_PRIVATE :
((!c->memfd_on_local) ?
PA_MEM_TYPE_SHARED_POSIX : PA_MEM_TYPE_SHARED_MEMFD);
if (!(c->mempool = pa_mempool_new(type, c->conf->shm_size, true))) {
if (!c->conf->disable_shm) {
......@@ -482,6 +487,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)) {
......@@ -500,7 +506,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);
......@@ -526,6 +540,26 @@ 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 && c->memfd_on_local) {
const char *reason;
pa_pstream_enable_memfd(c->pstream);
if (pa_mempool_is_memfd_backed(c->mempool))
if (pa_pstream_register_memfd_mempool(c->pstream, c->mempool, &reason))
pa_log("Failed to regester memfd mempool. Reason: %s", reason);
/* Even if memfd pool registration fails, the negotiated SHM type
* shall remain memfd as both endpoints claim to support it. */
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(c->memfd_on_local));
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) {
......@@ -593,8 +627,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) |
(c->memfd_on_local ? 0x40000000 : 0));
pa_tagstruct_put_arbitrary(t, cookie, sizeof(cookie));
#ifdef HAVE_CREDS
......
......@@ -88,6 +88,7 @@ struct pa_context {
bool is_local:1;
bool do_shm:1;
bool memfd_on_local:1;
bool server_specified:1;
bool no_fail:1;
bool do_autospawn:1;
......@@ -95,6 +96,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;
......
......@@ -22,6 +22,7 @@
#include <stdbool.h>
#include <pulsecore/creds.h>
#include <pulsecore/macro.h>
typedef enum pa_mem_type {
......@@ -48,4 +49,12 @@ static inline bool pa_mem_type_is_shared(pa_mem_type_t t) {
return (t == PA_MEM_TYPE_SHARED_POSIX) || (t == PA_MEM_TYPE_SHARED_MEMFD);
}
static inline bool pa_memfd_is_locally_supported() {
#if defined(HAVE_CREDS) && defined(HAVE_MEMFD)
return true;
#else
return false;
#endif
}
#endif
......@@ -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>
......@@ -2681,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);
......@@ -2705,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);
......@@ -2792,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()) {
pa_pstream_enable_memfd(c->pstream);
shm_type = PA_MEM_TYPE_SHARED_MEMFD;
} 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
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment