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.
This commit is contained in:
Wim Taymans 2018-02-08 10:02:17 +01:00
parent 06ba8c9a7e
commit 9d4b0d8358
9 changed files with 185 additions and 207 deletions

View file

@ -24,8 +24,6 @@
extern "C" { extern "C" {
#endif #endif
#include <dbus/dbus.h>
#include <spa/support/loop.h> #include <spa/support/loop.h>
#define SPA_TYPE__DBus SPA_TYPE_INTERFACE_BASE "DBus" #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" #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 { struct spa_dbus_connection {
#define SPA_VERSION_DBUS_CONNECTION 0 #define SPA_VERSION_DBUS_CONNECTION 0
uint32_t version; uint32_t version;
@ -40,9 +44,9 @@ struct spa_dbus_connection {
* Get the DBusConnection from a wraper * Get the DBusConnection from a wraper
* *
* \param conn the spa_dbus_connection wrapper * \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 * Destroy a dbus connection wrapper
* *
@ -69,13 +73,11 @@ struct spa_dbus {
* *
* \param dbus the dbus manager * \param dbus the dbus manager
* \param type the bus type to wrap * \param type the bus type to wrap
* \param error location for the error * \param error location for the DBusError
* \return a new dbus connection wrapper or NULL and \a error is * \return a new dbus connection wrapper or NULL on error
* set.
*/ */
struct spa_dbus_connection * (*get_connection) (struct spa_dbus *dbus, struct spa_dbus_connection * (*get_connection) (struct spa_dbus *dbus,
DBusBusType type, enum spa_dbus_type type);
DBusError *error);
}; };
#define spa_dbus_get_connection(d,...) (d)->get_connection((d),__VA_ARGS__) #define spa_dbus_get_connection(d,...) (d)->get_connection((d),__VA_ARGS__)

View file

@ -27,6 +27,8 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <dbus/dbus.h>
#include <spa/support/log.h> #include <spa/support/log.h>
#include <spa/support/type-map.h> #include <spa/support/type-map.h>
#include <spa/support/loop.h> #include <spa/support/loop.h>
@ -1187,7 +1189,6 @@ impl_init(const struct spa_handle_factory *factory,
{ {
struct spa_bt_monitor *this; struct spa_bt_monitor *this;
uint32_t i; uint32_t i;
DBusError err;
spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(factory != NULL, -EINVAL);
spa_return_val_if_fail(handle != 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); init_type(&this->type, this->map);
dbus_error_init(&err); this->dbus_connection = spa_dbus_get_connection(this->dbus, DBUS_BUS_SYSTEM);
this->dbus_connection = spa_dbus_get_connection(this->dbus, DBUS_BUS_SYSTEM, &err);
if (this->dbus_connection == NULL) { 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; return -EIO;
} }
this->conn = spa_dbus_connection_get(this->dbus_connection); this->conn = spa_dbus_connection_get(this->dbus_connection);

View file

@ -25,6 +25,8 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <dbus/dbus.h>
#include <spa/support/type-map.h> #include <spa/support/type-map.h>
#include <spa/support/log.h> #include <spa/support/log.h>
#include <spa/support/plugin.h> #include <spa/support/plugin.h>
@ -255,7 +257,7 @@ static void wakeup_main(void *userdata)
spa_loop_utils_enable_idle(impl->utils, this->dispatch_event, true); spa_loop_utils_enable_idle(impl->utils, this->dispatch_event, true);
} }
static DBusConnection * static void *
impl_connection_get(struct spa_dbus_connection *conn) impl_connection_get(struct spa_dbus_connection *conn)
{ {
struct connection *this = SPA_CONTAINER_OF(conn, struct connection, this); 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 * static struct spa_dbus_connection *
impl_get_connection(struct spa_dbus *dbus, impl_get_connection(struct spa_dbus *dbus,
DBusBusType type, enum spa_dbus_type type)
DBusError *error)
{ {
struct impl *impl = SPA_CONTAINER_OF(dbus, struct impl, dbus); struct impl *impl = SPA_CONTAINER_OF(dbus, struct impl, dbus);
struct connection *conn; struct connection *conn;
DBusError error;
dbus_error_init(error); dbus_error_init(&error);
conn = calloc(1, sizeof(struct connection)); conn = calloc(1, sizeof(struct connection));
conn->this = impl_connection; conn->this = impl_connection;
conn->impl = impl; conn->impl = impl;
conn->conn = dbus_bus_get_private(type, error); conn->conn = dbus_bus_get_private(type, &error);
if (conn->conn == NULL) if (conn->conn == NULL)
goto error; goto error;
@ -317,6 +319,8 @@ impl_get_connection(struct spa_dbus *dbus,
return &conn->this; return &conn->this;
error: error:
spa_log_error(impl->log, "Failed to connect to system bus: %s", error.message);
dbus_error_free(&error);
free(conn); free(conn);
return NULL; return NULL;
} }

View file

@ -5,6 +5,7 @@ pipewire_module_c_args = [
'-D_GNU_SOURCE', '-D_GNU_SOURCE',
] ]
if dbus_dep.found()
pipewire_module_flatpak = shared_library('pipewire-module-flatpak', [ 'module-flatpak.c' ], pipewire_module_flatpak = shared_library('pipewire-module-flatpak', [ 'module-flatpak.c' ],
c_args : pipewire_module_c_args, c_args : pipewire_module_c_args,
include_directories : [configinc, spa_inc], 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], 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' ], pipewire_module_autolink = shared_library('pipewire-module-autolink', [ 'module-autolink.c' ],
c_args : pipewire_module_c_args, c_args : pipewire_module_c_args,
include_directories : [configinc, spa_inc], include_directories : [configinc, spa_inc],

View file

@ -27,6 +27,8 @@
#include "config.h" #include "config.h"
#include <dbus/dbus.h>
#include <spa/support/dbus.h> #include <spa/support/dbus.h>
#include "pipewire/core.h" #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 pw_core *core = pw_module_get_core(module);
struct impl *impl; struct impl *impl;
DBusError error;
struct spa_dbus *dbus; struct spa_dbus *dbus;
const struct spa_support *support; const struct spa_support *support;
uint32_t n_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->type = pw_core_get_type(core);
impl->properties = properties; impl->properties = properties;
dbus_error_init(&error); impl->conn = spa_dbus_get_connection(dbus, SPA_DBUS_TYPE_SESSION);
impl->conn = spa_dbus_get_connection(dbus, DBUS_BUS_SESSION, &error);
if (impl->conn == NULL) if (impl->conn == NULL)
goto error; goto error;
@ -507,8 +506,7 @@ static int module_init(struct pw_module *module, struct pw_properties *propertie
error: error:
free(impl); free(impl);
pw_log_error("Failed to connect to system bus: %s", error.message); pw_log_error("Failed to connect to system bus");
dbus_error_free(&error);
return -ENOMEM; return -ENOMEM;
} }

View file

@ -1,5 +1,5 @@
/* PipeWire /* PipeWire
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com> * Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -16,6 +16,42 @@
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/resource.h>
#include <sys/eventfd.h>
#include "config.h"
#include <spa/support/dbus.h>
#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 2009 Lennart Poettering
Copyright 2010 David Henningsson <diwic@ubuntu.com> Copyright 2010 David Henningsson <diwic@ubuntu.com>
@ -41,15 +77,23 @@
SOFTWARE. SOFTWARE.
***/ ***/
#include <errno.h>
#include <stdlib.h>
#include <stdbool.h>
#include <dbus/dbus.h> #include <dbus/dbus.h>
#include <pipewire/log.h> #ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "rtkit.h" #ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1"
#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1"
/** \cond */ /** \cond */
struct pw_rtkit_bus { struct pw_rtkit_bus {
@ -90,22 +134,6 @@ void pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus)
free(system_bus); free(system_bus);
} }
#if defined(__linux__) && !defined(__ANDROID__)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
static pid_t _gettid(void) static pid_t _gettid(void)
{ {
return (pid_t) syscall(SYS_gettid); 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; return ret;
} }
#else static void module_destroy(void *data)
int pw_rtkit_make_realtime(struct pw_rtkit_bus *connection, pid_t thread, int priority)
{ {
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

View file

@ -22,60 +22,14 @@
#include <sys/resource.h> #include <sys/resource.h>
#include "pipewire/log.h" #include "pipewire/log.h"
#include "pipewire/rtkit.h"
#include "pipewire/data-loop.h" #include "pipewire/data-loop.h"
#include "pipewire/private.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) static void *do_loop(void *user_data)
{ {
struct pw_data_loop *this = user_data; struct pw_data_loop *this = user_data;
int res; int res;
make_realtime(this);
pw_log_debug("data-loop %p: enter thread", this); pw_log_debug("data-loop %p: enter thread", this);
pw_loop_enter(this->loop); pw_loop_enter(this->loop);

View file

@ -24,7 +24,6 @@ pipewire_headers = [
'proxy.h', 'proxy.h',
'remote.h', 'remote.h',
'resource.h', 'resource.h',
'rtkit.h',
'stream.h', 'stream.h',
'thread-loop.h', 'thread-loop.h',
'type.h', 'type.h',
@ -56,7 +55,6 @@ pipewire_sources = [
'remote.c', 'remote.c',
'resource.c', 'resource.c',
'stream.c', 'stream.c',
'rtkit.c',
'thread-loop.c', 'thread-loop.c',
'type.c', 'type.c',
'utils.c', 'utils.c',
@ -78,7 +76,7 @@ libpipewire = shared_library('pipewire-@0@'.format(apiversion), pipewire_sources
include_directories : [pipewire_inc, configinc, spa_inc], include_directories : [pipewire_inc, configinc, spa_inc],
link_with : spalib, link_with : spalib,
install : true, install : true,
dependencies : [dbus_dep, dl_lib, mathlib, pthread_lib], dependencies : [dl_lib, mathlib, pthread_lib],
) )
pipewire_dep = declare_dependency(link_with : libpipewire, pipewire_dep = declare_dependency(link_with : libpipewire,

View file

@ -1,93 +0,0 @@
/* PipeWire
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <sys/types.h>
#include <unistd.h>
#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__ */