From 41b47e726e00605b57f0db7e3604f992dc9c3bcd Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 4 Feb 2020 17:09:41 +0100 Subject: [PATCH] context: add some more defaults Make a property to allow mlock and use it. mlock in stream and filter when asked to mmap mem. --- pipewire-jack/src/pipewire-jack.c | 6 ++-- src/daemon/pipewire.conf.in | 1 + src/modules/module-client-node/remote-node.c | 18 ++++++----- src/pipewire/buffers.c | 6 +--- src/pipewire/context.c | 33 ++++++++++++++------ src/pipewire/filter.c | 9 ++++++ src/pipewire/private.h | 2 ++ src/pipewire/stream.c | 11 ++++++- 8 files changed, 61 insertions(+), 25 deletions(-) diff --git a/pipewire-jack/src/pipewire-jack.c b/pipewire-jack/src/pipewire-jack.c index 9c3d67014..cbd87ad29 100644 --- a/pipewire-jack/src/pipewire-jack.c +++ b/pipewire-jack/src/pipewire-jack.c @@ -311,6 +311,7 @@ struct client { unsigned int first:1; unsigned int thread_entered:1; unsigned int has_transport:1; + unsigned int allow_mlock:1; jack_position_t jack_position; jack_transport_state_t jack_state; @@ -1596,7 +1597,7 @@ static int client_node_port_use_buffers(void *object, } else { pw_log_warn("unknown buffer data type %d", d->type); } - if (mlock(d->data, d->maxsize) < 0) { + if (c->allow_mlock && mlock(d->data, d->maxsize) < 0) { pw_log_warn(NAME" %p: Failed to mlock memory %p %u: %s", c, d->data, d->maxsize, errno == ENOMEM ? @@ -2092,7 +2093,8 @@ jack_client_t * jack_client_open (const char *client_name, client->node_id = SPA_ID_INVALID; strncpy(client->name, client_name, JACK_CLIENT_NAME_SIZE); client->context.loop = pw_thread_loop_new(client_name, NULL); - client->context.context = pw_context_new(pw_thread_loop_get_loop(client->context.loop), NULL, 0); + client->context.context = pw_context_new(pw_thread_loop_get_loop(client->context.loop), NULL, 0); + client->allow_mlock = client->context.context->defaults.mem_allow_mlock; spa_list_init(&client->context.free_objects); spa_list_init(&client->context.nodes); spa_list_init(&client->context.ports); diff --git a/src/daemon/pipewire.conf.in b/src/daemon/pipewire.conf.in index 94936002c..327982204 100644 --- a/src/daemon/pipewire.conf.in +++ b/src/daemon/pipewire.conf.in @@ -3,6 +3,7 @@ #set-prop library.name.system support/libspa-support #set-prop context.data-loop.library.name.system support/libspa-support #set-prop link.max-buffers 64 +#set-prop mem.allow-mlock true #set-prop default.clock.rate 48000 #set-prop default.clock.quantum 1024 diff --git a/src/modules/module-client-node/remote-node.c b/src/modules/module-client-node/remote-node.c index 0cf9cae6b..24070b74c 100644 --- a/src/modules/module-client-node/remote-node.c +++ b/src/modules/module-client-node/remote-node.c @@ -76,8 +76,9 @@ struct node_data { struct pw_impl_node *node; struct spa_hook node_listener; - int do_free:1; - int have_transport:1; + unsigned int do_free:1; + unsigned int have_transport:1; + unsigned int allow_mlock:1; struct pw_client_node *client_node; struct spa_hook client_node_listener; @@ -629,7 +630,7 @@ client_node_port_use_buffers(void *object, bid->id = i; bid->mem = mm; - if (mlock(mm->ptr, mm->size) < 0) + if (data->allow_mlock && mlock(mm->ptr, mm->size) < 0) pw_log_warn("Failed to mlock memory %p %u: %s", mm->ptr, mm->size, errno == ENOMEM ? @@ -1144,11 +1145,11 @@ static struct pw_proxy *node_export(struct pw_core *core, void *object, bool do_ int i; client_node = pw_core_create_object(core, - "client-node", - PW_TYPE_INTERFACE_ClientNode, - PW_VERSION_CLIENT_NODE, - &node->properties->dict, - sizeof(struct node_data)); + "client-node", + PW_TYPE_INTERFACE_ClientNode, + PW_VERSION_CLIENT_NODE, + &node->properties->dict, + sizeof(struct node_data)); if (client_node == NULL) return NULL; @@ -1159,6 +1160,7 @@ static struct pw_proxy *node_export(struct pw_core *core, void *object, bool do_ data->context = pw_impl_node_get_context(node); data->client_node = (struct pw_client_node *)client_node; data->remote_id = SPA_ID_INVALID; + data->allow_mlock = data->context->defaults.mem_allow_mlock; node->exported = true; diff --git a/src/pipewire/buffers.c b/src/pipewire/buffers.c index 2a62fa183..32b7f0ecc 100644 --- a/src/pipewire/buffers.c +++ b/src/pipewire/buffers.c @@ -39,7 +39,6 @@ #define NAME "buffers" #define MAX_ALIGN 32 -#define MAX_BUFFERS 64 struct port { struct spa_node *node; @@ -241,10 +240,7 @@ int pw_buffers_negotiate(struct pw_context *context, uint32_t flags, offset += SPA_ROUND_UP_N(SPA_POD_SIZE(params[i]), 8); } - if ((str = pw_properties_get(context->properties, "link.max-buffers")) != NULL) - max_buffers = pw_properties_parse_int(str); - else - max_buffers = MAX_BUFFERS; + max_buffers = context->defaults.link_max_buffers; if ((str = pw_properties_get(context->properties, PW_KEY_CPU_MAX_ALIGN)) != NULL) align = pw_properties_parse_int(str); diff --git a/src/pipewire/context.c b/src/pipewire/context.c index a1f0c9b67..0b5985975 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -52,6 +52,8 @@ #define DEFAULT_VIDEO_HEIGHT 480 #define DEFAULT_VIDEO_RATE_NUM 25u #define DEFAULT_VIDEO_RATE_DENOM 1u +#define DEFAULT_LINK_MAX_BUFFERS 64u +#define DEFAULT_MEM_ALLOW_MLOCK true /** \cond */ struct impl { @@ -119,7 +121,7 @@ static void fill_properties(struct pw_context *context) pw_properties_set(properties, PW_KEY_CORE_NAME, context->core->info.name); } -static uint32_t get_default(struct pw_properties *properties, const char *name, uint32_t def) +static uint32_t get_default_int(struct pw_properties *properties, const char *name, uint32_t def) { uint32_t val; const char *str; @@ -130,19 +132,32 @@ static uint32_t get_default(struct pw_properties *properties, const char *name, return val; } +static bool get_default_bool(struct pw_properties *properties, const char *name, bool def) +{ + bool val; + const char *str; + if ((str = pw_properties_get(properties, name)) != NULL) + val = pw_properties_parse_bool(str); + else + val = def; + return val; +} + static void fill_defaults(struct pw_context *this) { struct pw_properties *p = this->properties; - this->defaults.clock_rate = get_default(p, "default.clock.rate", DEFAULT_CLOCK_RATE); - this->defaults.clock_quantum = get_default(p, "default.clock.quantum", DEFAULT_CLOCK_QUANTUM); - this->defaults.clock_min_quantum = get_default(p, "default.clock.min-quantum", DEFAULT_CLOCK_MIN_QUANTUM); - this->defaults.clock_max_quantum = get_default(p, "default.clock.max-quantum", DEFAULT_CLOCK_MAX_QUANTUM); + this->defaults.clock_rate = get_default_int(p, "default.clock.rate", DEFAULT_CLOCK_RATE); + this->defaults.clock_quantum = get_default_int(p, "default.clock.quantum", DEFAULT_CLOCK_QUANTUM); + this->defaults.clock_min_quantum = get_default_int(p, "default.clock.min-quantum", DEFAULT_CLOCK_MIN_QUANTUM); + this->defaults.clock_max_quantum = get_default_int(p, "default.clock.max-quantum", DEFAULT_CLOCK_MAX_QUANTUM); this->defaults.clock_quantum = SPA_CLAMP(this->defaults.clock_quantum, this->defaults.clock_min_quantum, this->defaults.clock_max_quantum); - this->defaults.video_size.width = get_default(p, "default.video.width", DEFAULT_VIDEO_WIDTH); - this->defaults.video_size.height = get_default(p, "default.video.height", DEFAULT_VIDEO_HEIGHT); - this->defaults.video_rate.num = get_default(p, "default.video.rate.num", DEFAULT_VIDEO_RATE_NUM); - this->defaults.video_rate.denom = get_default(p, "default.video.rate.denom", DEFAULT_VIDEO_RATE_DENOM); + this->defaults.video_size.width = get_default_int(p, "default.video.width", DEFAULT_VIDEO_WIDTH); + this->defaults.video_size.height = get_default_int(p, "default.video.height", DEFAULT_VIDEO_HEIGHT); + this->defaults.video_rate.num = get_default_int(p, "default.video.rate.num", DEFAULT_VIDEO_RATE_NUM); + this->defaults.video_rate.denom = get_default_int(p, "default.video.rate.denom", DEFAULT_VIDEO_RATE_DENOM); + this->defaults.link_max_buffers = get_default_int(p, "link.max-buffers", DEFAULT_LINK_MAX_BUFFERS); + this->defaults.mem_allow_mlock = get_default_bool(p, "mem.allow-mlock", DEFAULT_MEM_ALLOW_MLOCK); } /** Create a new context object diff --git a/src/pipewire/filter.c b/src/pipewire/filter.c index 1ba6de247..8992eccae 100644 --- a/src/pipewire/filter.c +++ b/src/pipewire/filter.c @@ -138,6 +138,7 @@ struct filter { unsigned int free_proxy:1; unsigned int subscribe:1; unsigned int draining:1; + unsigned int allow_mlock:1; }; static int get_param_index(uint32_t id) @@ -569,6 +570,13 @@ static int map_data(struct filter *impl, struct spa_data *data, int prot) pw_log_debug(NAME" %p: fd %"PRIi64" mapped %d %d %p", impl, data->fd, range.offset, range.size, data->data); + if (impl->allow_mlock && mlock(data->data, data->maxsize) < 0) { + pw_log_warn(NAME" %p: Failed to mlock memory %p %u: %s", impl, + data->data, data->maxsize, + errno == ENOMEM ? + "This is not a problem but for best performance, " + "consider increasing RLIMIT_MEMLOCK" : strerror(errno)); + } return 0; } @@ -947,6 +955,7 @@ filter_new(struct pw_context *context, const char *name, this->state = PW_FILTER_STATE_UNCONNECTED; impl->context = context; + impl->allow_mlock = context->defaults.mem_allow_mlock; return impl; diff --git a/src/pipewire/private.h b/src/pipewire/private.h index e705c8a23..97f8aadb9 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -55,6 +55,8 @@ struct defaults { uint32_t clock_max_quantum; struct spa_rectangle video_size; struct spa_fraction video_rate; + uint32_t link_max_buffers; + unsigned int mem_allow_mlock; }; #define MAX_PARAMS 32 diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 63283604b..fec730633 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -126,6 +126,7 @@ struct stream { unsigned int disconnecting:1; unsigned int free_proxy:1; unsigned int draining:1; + unsigned int allow_mlock:1; }; static int get_param_index(uint32_t id) @@ -547,10 +548,18 @@ static int map_data(struct stream *impl, struct spa_data *data, int prot) pw_log_error(NAME" %p: failed to mmap buffer mem: %m", impl); return -errno; } + data->data = SPA_MEMBER(ptr, range.start, void); pw_log_debug(NAME" %p: fd %"PRIi64" mapped %d %d %p", impl, data->fd, range.offset, range.size, data->data); + if (impl->allow_mlock && mlock(data->data, data->maxsize) < 0) { + pw_log_warn(NAME" %p: Failed to mlock memory %p %u: %s", impl, + data->data, data->maxsize, + errno == ENOMEM ? + "This is not a problem but for best performance, " + "consider increasing RLIMIT_MEMLOCK" : strerror(errno)); + } return 0; } @@ -1068,7 +1077,7 @@ stream_new(struct pw_context *context, const char *name, this->state = PW_STREAM_STATE_UNCONNECTED; impl->context = context; - + impl->allow_mlock = context->defaults.mem_allow_mlock; return impl;