Branch data Line data Source code
1 : : /*-*- Mode: C; c-basic-offset: 8 -*-*/
2 : :
3 : : /***
4 : : Copyright 2009 Lennart Poettering
5 : : Copyright 2010 David Henningsson <diwic@ubuntu.com>
6 : :
7 : : Permission is hereby granted, free of charge, to any person
8 : : obtaining a copy of this software and associated documentation files
9 : : (the "Software"), to deal in the Software without restriction,
10 : : including without limitation the rights to use, copy, modify, merge,
11 : : publish, distribute, sublicense, and/or sell copies of the Software,
12 : : and to permit persons to whom the Software is furnished to do so,
13 : : subject to the following conditions:
14 : :
15 : : The above copyright notice and this permission notice shall be
16 : : included in all copies or substantial portions of the Software.
17 : :
18 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 : : EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 : : MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 : : NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22 : : BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 : : ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 : : CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 : : SOFTWARE.
26 : : ***/
27 : :
28 : : #include <errno.h>
29 : :
30 : : #include "rtkit.h"
31 : :
32 : : #ifdef __linux__
33 : :
34 : : #ifndef _GNU_SOURCE
35 : : #define _GNU_SOURCE
36 : : #endif
37 : :
38 : : #ifdef HAVE_CONFIG_H
39 : : #include <config.h>
40 : : #endif
41 : :
42 : : #include <string.h>
43 : : #include <unistd.h>
44 : : #include <sys/types.h>
45 : : #include <sys/syscall.h>
46 : : #include <pulsecore/core-util.h>
47 : :
48 : : static pid_t _gettid(void) {
49 : 0 : return (pid_t) syscall(SYS_gettid);
50 : : }
51 : :
52 : 0 : static int translate_error(const char *name) {
53 [ # # ]: 0 : if (pa_streq(name, DBUS_ERROR_NO_MEMORY))
54 : : return -ENOMEM;
55 [ # # ][ # # ]: 0 : if (pa_streq(name, DBUS_ERROR_SERVICE_UNKNOWN) ||
56 : 0 : pa_streq(name, DBUS_ERROR_NAME_HAS_NO_OWNER))
57 : : return -ENOENT;
58 [ # # ][ # # ]: 0 : if (pa_streq(name, DBUS_ERROR_ACCESS_DENIED) ||
59 : 0 : pa_streq(name, DBUS_ERROR_AUTH_FAILED))
60 : : return -EACCES;
61 : :
62 : 0 : return -EIO;
63 : : }
64 : :
65 : 0 : static long long rtkit_get_int_property(DBusConnection *connection, const char* propname, long long* propval) {
66 : 0 : DBusMessage *m = NULL, *r = NULL;
67 : : DBusMessageIter iter, subiter;
68 : : dbus_int64_t i64;
69 : : dbus_int32_t i32;
70 : : DBusError error;
71 : : int current_type;
72 : : long long ret;
73 : 0 : const char * interfacestr = "org.freedesktop.RealtimeKit1";
74 : :
75 : 0 : dbus_error_init(&error);
76 : :
77 [ # # ]: 0 : if (!(m = dbus_message_new_method_call(
78 : : RTKIT_SERVICE_NAME,
79 : : RTKIT_OBJECT_PATH,
80 : : "org.freedesktop.DBus.Properties",
81 : : "Get"))) {
82 : : ret = -ENOMEM;
83 : : goto finish;
84 : : }
85 : :
86 [ # # ]: 0 : if (!dbus_message_append_args(
87 : : m,
88 : : DBUS_TYPE_STRING, &interfacestr,
89 : : DBUS_TYPE_STRING, &propname,
90 : : DBUS_TYPE_INVALID)) {
91 : : ret = -ENOMEM;
92 : : goto finish;
93 : : }
94 : :
95 [ # # ]: 0 : if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) {
96 : 0 : ret = translate_error(error.name);
97 : 0 : goto finish;
98 : : }
99 : :
100 [ # # ]: 0 : if (dbus_set_error_from_message(&error, r)) {
101 : 0 : ret = translate_error(error.name);
102 : 0 : goto finish;
103 : : }
104 : :
105 : 0 : ret = -EBADMSG;
106 : 0 : dbus_message_iter_init(r, &iter);
107 [ # # ]: 0 : while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) {
108 : :
109 [ # # ]: 0 : if (current_type == DBUS_TYPE_VARIANT) {
110 : 0 : dbus_message_iter_recurse(&iter, &subiter);
111 : :
112 [ # # ]: 0 : while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID) {
113 : :
114 [ # # ]: 0 : if (current_type == DBUS_TYPE_INT32) {
115 : 0 : dbus_message_iter_get_basic(&subiter, &i32);
116 : 0 : *propval = i32;
117 : 0 : ret = 0;
118 : : }
119 : :
120 [ # # ]: 0 : if (current_type == DBUS_TYPE_INT64) {
121 : 0 : dbus_message_iter_get_basic(&subiter, &i64);
122 : 0 : *propval = i64;
123 : 0 : ret = 0;
124 : : }
125 : :
126 : 0 : dbus_message_iter_next (&subiter);
127 : : }
128 : : }
129 : 0 : dbus_message_iter_next (&iter);
130 : : }
131 : :
132 : : finish:
133 : :
134 [ # # ]: 0 : if (m)
135 : 0 : dbus_message_unref(m);
136 : :
137 [ # # ]: 0 : if (r)
138 : 0 : dbus_message_unref(r);
139 : :
140 : 0 : dbus_error_free(&error);
141 : :
142 : 0 : return ret;
143 : : }
144 : :
145 : 0 : int rtkit_get_max_realtime_priority(DBusConnection *connection) {
146 : : long long retval;
147 : : int err;
148 : :
149 : 0 : err = rtkit_get_int_property(connection, "MaxRealtimePriority", &retval);
150 [ # # ]: 0 : return err < 0 ? err : retval;
151 : : }
152 : :
153 : 0 : int rtkit_get_min_nice_level(DBusConnection *connection, int* min_nice_level) {
154 : : long long retval;
155 : : int err;
156 : :
157 : 0 : err = rtkit_get_int_property(connection, "MinNiceLevel", &retval);
158 [ # # ]: 0 : if (err >= 0)
159 : 0 : *min_nice_level = retval;
160 : 0 : return err;
161 : : }
162 : :
163 : 0 : long long rtkit_get_rttime_usec_max(DBusConnection *connection) {
164 : : long long retval;
165 : : int err;
166 : :
167 : 0 : err = rtkit_get_int_property(connection, "RTTimeUSecMax", &retval);
168 [ # # ]: 0 : return err < 0 ? err : retval;
169 : : }
170 : :
171 : 0 : int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) {
172 : 0 : DBusMessage *m = NULL, *r = NULL;
173 : : dbus_uint64_t u64;
174 : : dbus_uint32_t u32;
175 : : DBusError error;
176 : : int ret;
177 : :
178 : 0 : dbus_error_init(&error);
179 : :
180 [ # # ]: 0 : if (thread == 0)
181 : 0 : thread = _gettid();
182 : :
183 [ # # ]: 0 : if (!(m = dbus_message_new_method_call(
184 : : RTKIT_SERVICE_NAME,
185 : : RTKIT_OBJECT_PATH,
186 : : "org.freedesktop.RealtimeKit1",
187 : : "MakeThreadRealtime"))) {
188 : : ret = -ENOMEM;
189 : : goto finish;
190 : : }
191 : :
192 : 0 : u64 = (dbus_uint64_t) thread;
193 : 0 : u32 = (dbus_uint32_t) priority;
194 : :
195 [ # # ]: 0 : if (!dbus_message_append_args(
196 : : m,
197 : : DBUS_TYPE_UINT64, &u64,
198 : : DBUS_TYPE_UINT32, &u32,
199 : : DBUS_TYPE_INVALID)) {
200 : : ret = -ENOMEM;
201 : : goto finish;
202 : : }
203 : :
204 [ # # ]: 0 : if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) {
205 : 0 : ret = translate_error(error.name);
206 : 0 : goto finish;
207 : : }
208 : :
209 : :
210 [ # # ]: 0 : if (dbus_set_error_from_message(&error, r)) {
211 : 0 : ret = translate_error(error.name);
212 : 0 : goto finish;
213 : : }
214 : :
215 : : ret = 0;
216 : :
217 : : finish:
218 : :
219 [ # # ]: 0 : if (m)
220 : 0 : dbus_message_unref(m);
221 : :
222 [ # # ]: 0 : if (r)
223 : 0 : dbus_message_unref(r);
224 : :
225 : 0 : dbus_error_free(&error);
226 : :
227 : 0 : return ret;
228 : : }
229 : :
230 : 0 : int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) {
231 : 0 : DBusMessage *m = NULL, *r = NULL;
232 : : dbus_uint64_t u64;
233 : : dbus_int32_t s32;
234 : : DBusError error;
235 : : int ret;
236 : :
237 : 0 : dbus_error_init(&error);
238 : :
239 [ # # ]: 0 : if (thread == 0)
240 : 0 : thread = _gettid();
241 : :
242 [ # # ]: 0 : if (!(m = dbus_message_new_method_call(
243 : : RTKIT_SERVICE_NAME,
244 : : RTKIT_OBJECT_PATH,
245 : : "org.freedesktop.RealtimeKit1",
246 : : "MakeThreadHighPriority"))) {
247 : : ret = -ENOMEM;
248 : : goto finish;
249 : : }
250 : :
251 : 0 : u64 = (dbus_uint64_t) thread;
252 : 0 : s32 = (dbus_int32_t) nice_level;
253 : :
254 [ # # ]: 0 : if (!dbus_message_append_args(
255 : : m,
256 : : DBUS_TYPE_UINT64, &u64,
257 : : DBUS_TYPE_INT32, &s32,
258 : : DBUS_TYPE_INVALID)) {
259 : : ret = -ENOMEM;
260 : : goto finish;
261 : : }
262 : :
263 : :
264 : :
265 [ # # ]: 0 : if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) {
266 : 0 : ret = translate_error(error.name);
267 : 0 : goto finish;
268 : : }
269 : :
270 : :
271 [ # # ]: 0 : if (dbus_set_error_from_message(&error, r)) {
272 : 0 : ret = translate_error(error.name);
273 : 0 : goto finish;
274 : : }
275 : :
276 : : ret = 0;
277 : :
278 : : finish:
279 : :
280 [ # # ]: 0 : if (m)
281 : 0 : dbus_message_unref(m);
282 : :
283 [ # # ]: 0 : if (r)
284 : 0 : dbus_message_unref(r);
285 : :
286 : 0 : dbus_error_free(&error);
287 : :
288 : 0 : return ret;
289 : : }
290 : :
291 : : #else
292 : :
293 : : int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) {
294 : : return -ENOTSUP;
295 : : }
296 : :
297 : : int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) {
298 : : return -ENOTSUP;
299 : : }
300 : :
301 : : int rtkit_get_max_realtime_priority(DBusConnection *connection) {
302 : : return -ENOTSUP;
303 : : }
304 : :
305 : : int rtkit_get_min_nice_level(DBusConnection *connection, int* min_nice_level) {
306 : : return -ENOTSUP;
307 : : }
308 : :
309 : : long long rtkit_get_rttime_usec_max(DBusConnection *connection) {
310 : : return -ENOTSUP;
311 : : }
312 : :
313 : : #endif
|