core: Support memfd transport; bump protocol version

Now that all layers in the stack support memfd blocks, add memfd
support for the daemon's global core mempool. Also introduce
"enable-memfd=" daemon argument and configuration option.

For now, memfd support is an opt-in feature to be activated only
when daemon's enable-memfd= is set to yes.

Signed-off-by: Ahmed S. Darwish <darwish.07@gmail.com>
This commit is contained in:
Ahmed S. Darwish 2016-04-15 23:07:36 +02:00 committed by Arun Raghavan
parent b1d47d60fc
commit d2a6afcab3
13 changed files with 122 additions and 24 deletions

View file

@ -63,6 +63,7 @@ enum {
ARG_CHECK,
ARG_NO_CPU_LIMIT,
ARG_DISABLE_SHM,
ARG_ENABLE_MEMFD,
ARG_DUMP_RESAMPLE_METHODS,
ARG_SYSTEM,
ARG_CLEANUP_SHM,
@ -100,6 +101,7 @@ static const struct option long_options[] = {
{"system", 2, 0, ARG_SYSTEM},
{"no-cpu-limit", 2, 0, ARG_NO_CPU_LIMIT},
{"disable-shm", 2, 0, ARG_DISABLE_SHM},
{"enable-memfd", 2, 0, ARG_ENABLE_MEMFD},
{"dump-resample-methods", 2, 0, ARG_DUMP_RESAMPLE_METHODS},
{"cleanup-shm", 2, 0, ARG_CLEANUP_SHM},
{NULL, 0, 0, 0}
@ -152,7 +154,8 @@ void pa_cmdline_help(const char *argv0) {
" --use-pid-file[=BOOL] Create a PID file\n"
" --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n"
" platforms that support it.\n"
" --disable-shm[=BOOL] Disable shared memory support.\n\n"
" --disable-shm[=BOOL] Disable shared memory support.\n"
" --enable-memfd[=BOOL] Enable memfd shared memory support.\n\n"
"STARTUP SCRIPT:\n"
" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with\n"
@ -389,6 +392,14 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
conf->disable_shm = !!b;
break;
case ARG_ENABLE_MEMFD:
if ((b = optarg ? pa_parse_boolean(optarg) : 1) < 0) {
pa_log(_("--enable-memfd expects boolean argument"));
goto fail;
}
conf->disable_memfd = !b;
break;
default:
goto fail;
}

View file

@ -92,6 +92,7 @@ static const pa_daemon_conf default_conf = {
#endif
.no_cpu_limit = true,
.disable_shm = false,
.disable_memfd = true,
.lock_memory = false,
.deferred_volume = true,
.default_n_fragments = 4,
@ -526,6 +527,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
{ "cpu-limit", pa_config_parse_not_bool, &c->no_cpu_limit, 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 },
{ "flat-volumes", pa_config_parse_bool, &c->flat_volumes, NULL },
{ "lock-memory", pa_config_parse_bool, &c->lock_memory, NULL },
{ "enable-deferred-volume", pa_config_parse_bool, &c->deferred_volume, NULL },

View file

@ -66,6 +66,7 @@ typedef struct pa_daemon_conf {
system_instance,
no_cpu_limit,
disable_shm,
disable_memfd,
disable_remixing,
disable_lfe_remixing,
load_default_script_file,

View file

@ -1017,7 +1017,9 @@ int main(int argc, char *argv[]) {
pa_assert_se(mainloop = pa_mainloop_new());
if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) {
if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm,
!conf->disable_shm && !conf->disable_memfd && pa_memfd_is_locally_supported(),
conf->shm_size))) {
pa_log(_("pa_core_new() failed."));
goto finish;
}

View file

@ -61,16 +61,19 @@ static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t o
static void core_free(pa_object *o);
pa_core* pa_core_new(pa_mainloop_api *m, bool shared, size_t shm_size) {
pa_core* pa_core_new(pa_mainloop_api *m, bool shared, bool enable_memfd, size_t shm_size) {
pa_core* c;
pa_mempool *pool;
pa_mem_type_t type;
int j;
pa_assert(m);
if (shared) {
if (!(pool = pa_mempool_new(PA_MEM_TYPE_SHARED_POSIX, shm_size, false))) {
pa_log_warn("Failed to allocate shared memory pool. Falling back to a normal memory pool.");
type = (enable_memfd) ? PA_MEM_TYPE_SHARED_MEMFD : PA_MEM_TYPE_SHARED_POSIX;
if (!(pool = pa_mempool_new(type, shm_size, false))) {
pa_log_warn("Failed to allocate %s memory pool. Falling back to a normal memory pool.",
pa_mem_type_to_string(type));
shared = false;
}
}

View file

@ -218,7 +218,7 @@ enum {
PA_CORE_MESSAGE_MAX
};
pa_core* pa_core_new(pa_mainloop_api *m, bool shared, size_t shm_size);
pa_core* pa_core_new(pa_mainloop_api *m, bool shared, bool enable_memfd, size_t shm_size);
/* Check whether no one is connected to this core */
void pa_core_check_idle(pa_core *c);

View file

@ -2598,7 +2598,7 @@ 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;
@ -2631,20 +2631,25 @@ 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, true))) {
if (!(c->rw_mempool = pa_mempool_new(shm_type, c->protocol->core->shm_size, true))) {
pa_log_warn("Disabling srbchannel, reason: Failed to allocate shared "
"writable memory pool.");
return;
}
if (shm_type == PA_MEM_TYPE_SHARED_MEMFD) {
const char *reason;
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);
goto fail;
}
}
pa_mempool_set_is_remote_writable(c->rw_mempool, true);
srb = pa_srbchannel_new(c->protocol->core->mainloop, c->rw_mempool);
if (!srb) {
pa_log_debug("Failed to create srbchannel");
pa_mempool_unref(c->rw_mempool);
c->rw_mempool = NULL;
return;
goto fail;
}
pa_log_debug("Enabling srbchannel...");
pa_srbchannel_export(srb, &srbt);
@ -2664,6 +2669,13 @@ static void setup_srbchannel(pa_native_connection *c) {
pa_pstream_send_memblock(c->pstream, 0, 0, 0, &mc);
c->srbpending = srb;
return;
fail:
if (c->rw_mempool) {
pa_mempool_unref(c->rw_mempool);
c->rw_mempool = NULL;
}
}
static void command_enable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
@ -2682,7 +2694,7 @@ 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;
bool memfd_on_remote = false, do_memfd = false;
pa_tagstruct *reply;
pa_mem_type_t shm_type;
bool shm_on_remote = false, do_shm;
@ -2777,7 +2789,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
}
}
/* Enable shared memory support if possible */
/* Enable shared memory and memfd support if possible */
do_shm =
pa_mempool_is_shared(c->protocol->core->mempool) &&
c->is_local;
@ -2803,9 +2815,12 @@ 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);
do_memfd =
do_shm && pa_mempool_is_memfd_backed(c->protocol->core->mempool);
shm_type = PA_MEM_TYPE_PRIVATE;
if (do_shm) {
if (c->version >= 31 && memfd_on_remote && pa_memfd_is_locally_supported()) {
if (c->version >= 31 && memfd_on_remote && do_memfd) {
pa_pstream_enable_memfd(c->pstream);
shm_type = PA_MEM_TYPE_SHARED_MEMFD;
} else
@ -2817,7 +2832,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
reply = reply_new(tag);
pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0) |
(pa_memfd_is_locally_supported() ? 0x40000000 : 0));
(do_memfd ? 0x40000000 : 0));
#ifdef HAVE_CREDS
{
@ -2834,7 +2849,19 @@ 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);
/* The client enables memfd transport on its pstream only after
* inspecting our version flags to see if we support memfds too.
*
* Thus register any pools after sending the server's version
* flags and _never_ before it. */
if (shm_type == PA_MEM_TYPE_SHARED_MEMFD) {
const char *reason;
if (pa_pstream_register_memfd_mempool(c->pstream, c->protocol->core->mempool, &reason))
pa_log("Failed to register memfd mempool. Reason: %s", reason);
}
setup_srbchannel(c, shm_type);
}
static void command_register_memfd_shmid(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {