From 9d4b0d83587bd2bbd5430a20e94d0bab4e6d27c0 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 8 Feb 2018 10:02:17 +0100 Subject: [PATCH] dbus: move rtkit to module Move the rtkit code to a module. Make sure we don't need to include the dbus headers in the spa dbus interface. This removes the dependency on dbus. --- spa/include/spa/support/dbus.h | 20 +- spa/plugins/bluez5/bluez5-monitor.c | 9 +- spa/plugins/support/dbus.c | 14 +- src/modules/meson.build | 11 ++ src/modules/module-flatpak.c | 10 +- .../rtkit.c => modules/module-rtkit.c} | 185 ++++++++++++++---- src/pipewire/data-loop.c | 46 ----- src/pipewire/meson.build | 4 +- src/pipewire/rtkit.h | 93 --------- 9 files changed, 185 insertions(+), 207 deletions(-) rename src/{pipewire/rtkit.c => modules/module-rtkit.c} (70%) delete mode 100644 src/pipewire/rtkit.h diff --git a/spa/include/spa/support/dbus.h b/spa/include/spa/support/dbus.h index c6f6db619..778043389 100644 --- a/spa/include/spa/support/dbus.h +++ b/spa/include/spa/support/dbus.h @@ -24,8 +24,6 @@ extern "C" { #endif -#include - #include #define SPA_TYPE__DBus SPA_TYPE_INTERFACE_BASE "DBus" @@ -33,6 +31,12 @@ extern "C" { #define SPA_TYPE_DBUS__Connection SPA_TYPE_DBUS_BASE "Connection" +enum spa_dbus_type { + SPA_DBUS_TYPE_SESSION, /**< The login session bus */ + SPA_DBUS_TYPE_SYSTEM, /**< The systemwide bus */ + SPA_DBUS_TYPE_STARTER /**< The bus that started us, if any */ +}; + struct spa_dbus_connection { #define SPA_VERSION_DBUS_CONNECTION 0 uint32_t version; @@ -40,9 +44,9 @@ struct spa_dbus_connection { * Get the DBusConnection from a wraper * * \param conn the spa_dbus_connection wrapper - * \return a DBusConnection + * \return a pointer of type DBusConnection */ - DBusConnection *(*get) (struct spa_dbus_connection *conn); + void *(*get) (struct spa_dbus_connection *conn); /** * Destroy a dbus connection wrapper * @@ -69,13 +73,11 @@ struct spa_dbus { * * \param dbus the dbus manager * \param type the bus type to wrap - * \param error location for the error - * \return a new dbus connection wrapper or NULL and \a error is - * set. + * \param error location for the DBusError + * \return a new dbus connection wrapper or NULL on error */ struct spa_dbus_connection * (*get_connection) (struct spa_dbus *dbus, - DBusBusType type, - DBusError *error); + enum spa_dbus_type type); }; #define spa_dbus_get_connection(d,...) (d)->get_connection((d),__VA_ARGS__) diff --git a/spa/plugins/bluez5/bluez5-monitor.c b/spa/plugins/bluez5/bluez5-monitor.c index a4c8470cb..2e65f1a1b 100644 --- a/spa/plugins/bluez5/bluez5-monitor.c +++ b/spa/plugins/bluez5/bluez5-monitor.c @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -1187,7 +1189,6 @@ impl_init(const struct spa_handle_factory *factory, { struct spa_bt_monitor *this; uint32_t i; - DBusError err; spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL); @@ -1215,11 +1216,9 @@ impl_init(const struct spa_handle_factory *factory, } init_type(&this->type, this->map); - dbus_error_init(&err); - - this->dbus_connection = spa_dbus_get_connection(this->dbus, DBUS_BUS_SYSTEM, &err); + this->dbus_connection = spa_dbus_get_connection(this->dbus, DBUS_BUS_SYSTEM); if (this->dbus_connection == NULL) { - spa_log_error(this->log, "no dbus connection: %s", err.message); + spa_log_error(this->log, "no dbus connection"); return -EIO; } this->conn = spa_dbus_connection_get(this->dbus_connection); diff --git a/spa/plugins/support/dbus.c b/spa/plugins/support/dbus.c index 9f6d7ac70..8f9787352 100644 --- a/spa/plugins/support/dbus.c +++ b/spa/plugins/support/dbus.c @@ -25,6 +25,8 @@ #include #include +#include + #include #include #include @@ -255,7 +257,7 @@ static void wakeup_main(void *userdata) spa_loop_utils_enable_idle(impl->utils, this->dispatch_event, true); } -static DBusConnection * +static void * impl_connection_get(struct spa_dbus_connection *conn) { struct connection *this = SPA_CONTAINER_OF(conn, struct connection, this); @@ -286,18 +288,18 @@ static const struct spa_dbus_connection impl_connection = { static struct spa_dbus_connection * impl_get_connection(struct spa_dbus *dbus, - DBusBusType type, - DBusError *error) + enum spa_dbus_type type) { struct impl *impl = SPA_CONTAINER_OF(dbus, struct impl, dbus); struct connection *conn; + DBusError error; - dbus_error_init(error); + dbus_error_init(&error); conn = calloc(1, sizeof(struct connection)); conn->this = impl_connection; conn->impl = impl; - conn->conn = dbus_bus_get_private(type, error); + conn->conn = dbus_bus_get_private(type, &error); if (conn->conn == NULL) goto error; @@ -317,6 +319,8 @@ impl_get_connection(struct spa_dbus *dbus, return &conn->this; error: + spa_log_error(impl->log, "Failed to connect to system bus: %s", error.message); + dbus_error_free(&error); free(conn); return NULL; } diff --git a/src/modules/meson.build b/src/modules/meson.build index c47e798cd..c8a60a9f8 100644 --- a/src/modules/meson.build +++ b/src/modules/meson.build @@ -5,6 +5,7 @@ pipewire_module_c_args = [ '-D_GNU_SOURCE', ] +if dbus_dep.found() pipewire_module_flatpak = shared_library('pipewire-module-flatpak', [ 'module-flatpak.c' ], c_args : pipewire_module_c_args, include_directories : [configinc, spa_inc], @@ -14,6 +15,16 @@ pipewire_module_flatpak = shared_library('pipewire-module-flatpak', [ 'module-fl dependencies : [dbus_dep, mathlib, dl_lib, pipewire_dep], ) +pipewire_module_rtkit = shared_library('pipewire-module-rtkit', [ 'module-rtkit.c' ], + c_args : pipewire_module_c_args, + include_directories : [configinc, spa_inc], + link_with : spalib, + install : true, + install_dir : modules_install_dir, + dependencies : [dbus_dep, mathlib, dl_lib, pipewire_dep], +) +endif + pipewire_module_autolink = shared_library('pipewire-module-autolink', [ 'module-autolink.c' ], c_args : pipewire_module_c_args, include_directories : [configinc, spa_inc], diff --git a/src/modules/module-flatpak.c b/src/modules/module-flatpak.c index 10ad05a91..13f4342c5 100644 --- a/src/modules/module-flatpak.c +++ b/src/modules/module-flatpak.c @@ -27,6 +27,8 @@ #include "config.h" +#include + #include #include "pipewire/core.h" @@ -469,7 +471,6 @@ static int module_init(struct pw_module *module, struct pw_properties *propertie { struct pw_core *core = pw_module_get_core(module); struct impl *impl; - DBusError error; struct spa_dbus *dbus; const struct spa_support *support; uint32_t n_support; @@ -490,9 +491,7 @@ static int module_init(struct pw_module *module, struct pw_properties *propertie impl->type = pw_core_get_type(core); impl->properties = properties; - dbus_error_init(&error); - - impl->conn = spa_dbus_get_connection(dbus, DBUS_BUS_SESSION, &error); + impl->conn = spa_dbus_get_connection(dbus, SPA_DBUS_TYPE_SESSION); if (impl->conn == NULL) goto error; @@ -507,8 +506,7 @@ static int module_init(struct pw_module *module, struct pw_properties *propertie error: free(impl); - pw_log_error("Failed to connect to system bus: %s", error.message); - dbus_error_free(&error); + pw_log_error("Failed to connect to system bus"); return -ENOMEM; } diff --git a/src/pipewire/rtkit.c b/src/modules/module-rtkit.c similarity index 70% rename from src/pipewire/rtkit.c rename to src/modules/module-rtkit.c index d28cf1b8c..b83db9c42 100644 --- a/src/pipewire/rtkit.c +++ b/src/modules/module-rtkit.c @@ -1,5 +1,5 @@ /* PipeWire - * Copyright (C) 2015 Wim Taymans + * Copyright (C) 2016 Wim Taymans * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -16,6 +16,42 @@ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include + +#include "pipewire/core.h" +#include "pipewire/interfaces.h" +#include "pipewire/link.h" +#include "pipewire/log.h" +#include "pipewire/module.h" +#include "pipewire/utils.h" + +struct impl { + struct pw_core *core; + struct pw_type *type; + struct pw_properties *properties; + + struct spa_loop *loop; + struct spa_source source; + + struct spa_hook module_listener; +}; + /*** Copyright 2009 Lennart Poettering Copyright 2010 David Henningsson @@ -41,15 +77,23 @@ SOFTWARE. ***/ -#include -#include -#include - #include -#include +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif -#include "rtkit.h" +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1" +#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1" /** \cond */ struct pw_rtkit_bus { @@ -90,22 +134,6 @@ void pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus) free(system_bus); } -#if defined(__linux__) && !defined(__ANDROID__) - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - - static pid_t _gettid(void) { return (pid_t) syscall(SYS_gettid); @@ -349,31 +377,108 @@ int pw_rtkit_make_high_priority(struct pw_rtkit_bus *connection, pid_t thread, i return ret; } -#else - -int pw_rtkit_make_realtime(struct pw_rtkit_bus *connection, pid_t thread, int priority) +static void module_destroy(void *data) { - return -ENOTSUP; + struct impl *impl = data; + + spa_hook_remove(&impl->module_listener); + + if (impl->properties) + pw_properties_free(impl->properties); + + free(impl); } -int pw_rtkit_make_high_priority(struct pw_rtkit_bus *connection, pid_t thread, int nice_level) +static const struct pw_module_events module_events = { + PW_VERSION_MODULE_EVENTS, + .destroy = module_destroy, +}; + +static void idle_func(struct spa_source *source) { - return -ENOTSUP; + struct impl *impl = source->data; + struct sched_param sp; + struct pw_rtkit_bus *system_bus; + struct rlimit rl; + int r, rtprio; + long long rttime; + uint64_t count; + + rtprio = 20; + rttime = 20000; + + spa_zero(sp); + sp.sched_priority = rtprio; + + if (pthread_setschedparam(pthread_self(), SCHED_OTHER | SCHED_RESET_ON_FORK, &sp) == 0) { + pw_log_debug("SCHED_OTHER|SCHED_RESET_ON_FORK worked."); + return; + } + system_bus = pw_rtkit_bus_get_system(); + + rl.rlim_cur = rl.rlim_max = rttime; + if ((r = setrlimit(RLIMIT_RTTIME, &rl)) < 0) + pw_log_debug("setrlimit() failed: %s", strerror(errno)); + + if (rttime >= 0) { + r = getrlimit(RLIMIT_RTTIME, &rl); + if (r >= 0 && (long long) rl.rlim_max > rttime) { + pw_log_debug("Clamping rlimit-rttime to %lld for RealtimeKit", rttime); + rl.rlim_cur = rl.rlim_max = rttime; + + if ((r = setrlimit(RLIMIT_RTTIME, &rl)) < 0) + pw_log_debug("setrlimit() failed: %s", strerror(errno)); + } + } + + if ((r = pw_rtkit_make_realtime(system_bus, 0, rtprio)) < 0) { + pw_log_debug("could not make thread realtime: %s", strerror(r)); + } else { + pw_log_debug("thread made realtime"); + } + pw_rtkit_bus_free(system_bus); + + read(impl->source.fd, &count, sizeof(uint64_t)); } -int pw_rtkit_get_max_realtime_priority(struct pw_rtkit_bus *connection) +static int module_init(struct pw_module *module, struct pw_properties *properties) { - return -ENOTSUP; + struct pw_core *core = pw_module_get_core(module); + struct impl *impl; + struct spa_loop *loop; + const struct spa_support *support; + uint32_t n_support; + + support = pw_core_get_support(core, &n_support); + + loop = spa_support_find(support, n_support, SPA_TYPE_LOOP__DataLoop); + if (loop == NULL) + return -ENOTSUP; + + impl = calloc(1, sizeof(struct impl)); + if (impl == NULL) + return -ENOMEM; + + pw_log_debug("module %p: new", impl); + + impl->core = core; + impl->type = pw_core_get_type(core); + impl->properties = properties; + impl->loop = loop; + + impl->source.loop = loop; + impl->source.func = idle_func; + impl->source.data = impl; + impl->source.fd = eventfd(1, EFD_CLOEXEC | EFD_NONBLOCK); + impl->source.mask = SPA_IO_IN; + spa_loop_add_source(impl->loop, &impl->source); + + pw_module_add_listener(module, &impl->module_listener, &module_events, impl); + + return 0; } -int pw_rtkit_get_min_nice_level(struct pw_rtkit_bus *connection, int *min_nice_level) +int pipewire__module_init(struct pw_module *module, const char *args) { - return -ENOTSUP; + return module_init(module, NULL); } - -long long pw_rtkit_get_rttime_usec_max(struct pw_rtkit_bus *connection) -{ - return -ENOTSUP; -} - -#endif diff --git a/src/pipewire/data-loop.c b/src/pipewire/data-loop.c index 2f8d31ceb..9c4dda28d 100644 --- a/src/pipewire/data-loop.c +++ b/src/pipewire/data-loop.c @@ -22,60 +22,14 @@ #include #include "pipewire/log.h" -#include "pipewire/rtkit.h" #include "pipewire/data-loop.h" #include "pipewire/private.h" -static void make_realtime(struct pw_data_loop *this) -{ - struct sched_param sp; - struct pw_rtkit_bus *system_bus; - struct rlimit rl; - int r, rtprio; - long long rttime; - - rtprio = 20; - rttime = 20000; - - spa_zero(sp); - sp.sched_priority = rtprio; - - if (pthread_setschedparam(pthread_self(), SCHED_OTHER | SCHED_RESET_ON_FORK, &sp) == 0) { - pw_log_debug("SCHED_OTHER|SCHED_RESET_ON_FORK worked."); - return; - } - system_bus = pw_rtkit_bus_get_system(); - - rl.rlim_cur = rl.rlim_max = rttime; - if ((r = setrlimit(RLIMIT_RTTIME, &rl)) < 0) - pw_log_debug("setrlimit() failed: %s", strerror(errno)); - - if (rttime >= 0) { - r = getrlimit(RLIMIT_RTTIME, &rl); - if (r >= 0 && (long long) rl.rlim_max > rttime) { - pw_log_debug("Clamping rlimit-rttime to %lld for RealtimeKit", rttime); - rl.rlim_cur = rl.rlim_max = rttime; - - if ((r = setrlimit(RLIMIT_RTTIME, &rl)) < 0) - pw_log_debug("setrlimit() failed: %s", strerror(errno)); - } - } - - if ((r = pw_rtkit_make_realtime(system_bus, 0, rtprio)) < 0) { - pw_log_debug("could not make thread realtime: %s", strerror(r)); - } else { - pw_log_debug("thread made realtime"); - } - pw_rtkit_bus_free(system_bus); -} - static void *do_loop(void *user_data) { struct pw_data_loop *this = user_data; int res; - make_realtime(this); - pw_log_debug("data-loop %p: enter thread", this); pw_loop_enter(this->loop); diff --git a/src/pipewire/meson.build b/src/pipewire/meson.build index 9c480d1a3..9929d498e 100644 --- a/src/pipewire/meson.build +++ b/src/pipewire/meson.build @@ -24,7 +24,6 @@ pipewire_headers = [ 'proxy.h', 'remote.h', 'resource.h', - 'rtkit.h', 'stream.h', 'thread-loop.h', 'type.h', @@ -56,7 +55,6 @@ pipewire_sources = [ 'remote.c', 'resource.c', 'stream.c', - 'rtkit.c', 'thread-loop.c', 'type.c', 'utils.c', @@ -78,7 +76,7 @@ libpipewire = shared_library('pipewire-@0@'.format(apiversion), pipewire_sources include_directories : [pipewire_inc, configinc, spa_inc], link_with : spalib, install : true, - dependencies : [dbus_dep, dl_lib, mathlib, pthread_lib], + dependencies : [dl_lib, mathlib, pthread_lib], ) pipewire_dep = declare_dependency(link_with : libpipewire, diff --git a/src/pipewire/rtkit.h b/src/pipewire/rtkit.h deleted file mode 100644 index a40e2d123..000000000 --- a/src/pipewire/rtkit.h +++ /dev/null @@ -1,93 +0,0 @@ -/* PipeWire - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __PIPEWIRE_RTKIT_H__ -#define __PIPEWIRE_RTKIT_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1" -#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1" - -/** \class pw_rtkit - * - * RTKit helpers - */ -/** Get an RTKit bus \memberof pw_rtkit */ -struct pw_rtkit_bus * -pw_rtkit_bus_get_system(void); - -/** Free an RTKit bus \memberof pw_rtkit */ -void -pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus); - - -/** This is mostly equivalent to sched_setparam(thread, SCHED_RR, { - * .sched_priority = priority }). 'thread' needs to be a kernel thread - * id as returned by gettid(), not a pthread_t! If 'thread' is 0 the - * current thread is used. The returned value is a negative errno - * style error code, or 0 on success. - * \memberof pw_rtkit - */ -int -pw_rtkit_make_realtime(struct pw_rtkit_bus *system_bus, pid_t thread, int priority); - - -/** This is mostly equivalent to setpriority(PRIO_PROCESS, thread, - * nice_level). 'thread' needs to be a kernel thread id as returned by - * gettid(), not a pthread_t! If 'thread' is 0 the current thread is - * used. The returned value is a negative errno style error code, or - * 0 on success. - * \memberof pw_rtkit - */ -int -pw_rtkit_make_high_priority(struct pw_rtkit_bus *system_bus, pid_t thread, int nice_level); - -/** Return the maximum value of realtime priority available. Realtime requests - * above this value will fail. A negative value is an errno style error code. - * \memberof pw_rtkit - */ -int -pw_rtkit_get_max_realtime_priority(struct pw_rtkit_bus *system_bus); - -/** Retreive the minimum value of nice level available. High prio requests - * below this value will fail. The returned value is a negative errno - * style error code, or 0 on success. - * \memberof pw_rtkit - */ -int -pw_rtkit_get_min_nice_level(struct pw_rtkit_bus *system_bus, int *min_nice_level); - -/** Return the maximum value of RLIMIT_RTTIME to set before attempting a - * realtime request. A negative value is an errno style error code. - * \memberof pw_rtkit - */ -long long -pw_rtkit_get_rttime_usec_max(struct pw_rtkit_bus *system_bus); - -#ifdef __cplusplus -} -#endif - -#endif /* __PIPEWIRE_RTKIT_H__ */