From 44d7c9ad9bcfd8ab55d4ef7f6595c7ffd65da35d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 00:34:43 +0000 Subject: add nice and rtprio resource limit support; make rtprio and nice level to use configurable; some minor updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2010 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 177 +++++++++++++++++++++++++++++++++------------- src/daemon/daemon-conf.h | 24 +++++-- src/daemon/daemon.conf.in | 89 +++++++++++++++-------- src/daemon/main.c | 6 ++ 4 files changed, 210 insertions(+), 86 deletions(-) (limited to 'src/daemon') diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 920e3717..089b12fc 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -53,10 +54,13 @@ static const pa_daemon_conf default_conf = { .cmd = PA_CMD_DAEMON, - .daemonize = 0, - .fail = 1, - .high_priority = 0, - .disallow_module_loading = 0, + .daemonize = FALSE, + .fail = TRUE, + .high_priority = TRUE, + .nice_level = -11, + .realtime_scheduling = FALSE, + .realtime_priority = 5, /* Half of JACK's default rtprio */ + .disallow_module_loading = FALSE, .exit_idle_time = -1, .module_idle_time = 20, .scache_idle_time = 20, @@ -68,25 +72,31 @@ static const pa_daemon_conf default_conf = { .log_level = PA_LOG_NOTICE, .resample_method = PA_RESAMPLER_AUTO, .config_file = NULL, - .use_pid_file = 1, - .system_instance = 0, - .no_cpu_limit = 0, - .disable_shm = 0, + .use_pid_file = TRUE, + .system_instance = FALSE, + .no_cpu_limit = FALSE, + .disable_shm = FALSE, .default_n_fragments = 4, .default_fragment_size_msec = 25, .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 } #ifdef HAVE_SYS_RESOURCE_H - , .rlimit_as = { .value = 0, .is_set = 0 }, - .rlimit_core = { .value = 0, .is_set = 0 }, - .rlimit_data = { .value = 0, .is_set = 0 }, - .rlimit_fsize = { .value = 0, .is_set = 0 }, - .rlimit_nofile = { .value = 256, .is_set = 1 }, - .rlimit_stack = { .value = 0, .is_set = 0 } + , .rlimit_as = { .value = 0, .is_set = FALSE }, + .rlimit_core = { .value = 0, .is_set = FALSE }, + .rlimit_data = { .value = 0, .is_set = FALSE }, + .rlimit_fsize = { .value = 0, .is_set = FALSE }, + .rlimit_nofile = { .value = 256, .is_set = TRUE }, + .rlimit_stack = { .value = 0, .is_set = FALSE } #ifdef RLIMIT_NPROC - , .rlimit_nproc = { .value = 0, .is_set = 0 } + , .rlimit_nproc = { .value = 0, .is_set = FALSE } #endif #ifdef RLIMIT_MEMLOCK - , .rlimit_memlock = { .value = 16384, .is_set = 1 } + , .rlimit_memlock = { .value = 16384, .is_set = TRUE } +#endif +#ifdef RLIMIT_NICE + , .rlimit_nice = { .value = 31, .is_set = TRUE } /* nice level of -11 */ +#endif +#ifdef RLIMIT_RTPRIO + , .rlimit_rtprio = { .value = 9, .is_set = TRUE } /* One below JACK's default for the server */ #endif #endif }; @@ -334,6 +344,42 @@ static int parse_fragment_size_msec(const char *filename, unsigned line, const c return 0; } +static int parse_nice_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; + int32_t level; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atoi(rvalue, &level) < 0 || level < -20 || level > 19) { + pa_log("[%s:%u] Invalid nice level '%s'.", filename, line, rvalue); + return -1; + } + + c->nice_level = (int) level; + return 0; +} + +static int parse_rtprio(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; + int32_t rtprio; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atoi(rvalue, &rtprio) < 0 || rtprio < sched_get_priority_min(SCHED_FIFO) || rtprio > sched_get_priority_max(SCHED_FIFO)) { + pa_log("[%s:%u] Invalid realtime priority '%s'.", filename, line, rvalue); + return -1; + } + + c->realtime_priority = (int) rtprio; + return 0; +} + int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { int r = -1; FILE *f = NULL; @@ -342,25 +388,28 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "daemonize", pa_config_parse_bool, NULL }, { "fail", pa_config_parse_bool, NULL }, { "high-priority", pa_config_parse_bool, NULL }, + { "realtime-scheduling", pa_config_parse_bool, NULL }, { "disallow-module-loading", pa_config_parse_bool, NULL }, + { "use-pid-file", pa_config_parse_bool, NULL }, + { "system-instance", pa_config_parse_bool, NULL }, + { "no-cpu-limit", pa_config_parse_bool, NULL }, + { "disable-shm", pa_config_parse_bool, NULL }, { "exit-idle-time", pa_config_parse_int, NULL }, { "module-idle-time", pa_config_parse_int, NULL }, { "scache-idle-time", pa_config_parse_int, NULL }, + { "realtime-priority", parse_rtprio, NULL }, { "dl-search-path", pa_config_parse_string, NULL }, { "default-script-file", pa_config_parse_string, NULL }, { "log-target", parse_log_target, NULL }, { "log-level", parse_log_level, NULL }, { "verbose", parse_log_level, NULL }, { "resample-method", parse_resample_method, NULL }, - { "use-pid-file", pa_config_parse_bool, NULL }, - { "system-instance", pa_config_parse_bool, NULL }, - { "no-cpu-limit", pa_config_parse_bool, NULL }, - { "disable-shm", pa_config_parse_bool, NULL }, { "default-sample-format", parse_sample_format, NULL }, { "default-sample-rate", parse_sample_rate, NULL }, { "default-sample-channels", parse_sample_channels, NULL }, { "default-fragments", parse_fragments, NULL }, { "default-fragment-size-msec", parse_fragment_size_msec, NULL }, + { "nice-level", parse_nice_level, NULL }, #ifdef HAVE_SYS_RESOURCE_H { "rlimit-as", parse_rlimit, NULL }, { "rlimit-core", parse_rlimit, NULL }, @@ -374,6 +423,12 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { #ifdef RLIMIT_MEMLOCK { "rlimit-memlock", parse_rlimit, NULL }, #endif +#ifdef RLIMIT_NICE + { "rlimit-nice", parse_rlimit, NULL }, +#endif +#ifdef RLIMIT_RTPRIO + { "rlimit-rtprio", parse_rlimit, NULL }, +#endif #endif { NULL, NULL, NULL }, }; @@ -381,40 +436,55 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[0].data = &c->daemonize; table[1].data = &c->fail; table[2].data = &c->high_priority; - table[3].data = &c->disallow_module_loading; - table[4].data = &c->exit_idle_time; - table[5].data = &c->module_idle_time; - table[6].data = &c->scache_idle_time; - table[7].data = &c->dl_search_path; - table[8].data = &c->default_script_file; - table[9].data = c; - table[10].data = c; - table[11].data = c; + table[3].data = &c->realtime_scheduling; + table[4].data = &c->disallow_module_loading; + table[5].data = &c->use_pid_file; + table[6].data = &c->system_instance; + table[7].data = &c->no_cpu_limit; + table[8].data = &c->disable_shm; + table[9].data = &c->exit_idle_time; + table[10].data = &c->module_idle_time; + table[11].data = &c->scache_idle_time; table[12].data = c; - table[13].data = &c->use_pid_file; - table[14].data = &c->system_instance; - table[15].data = &c->no_cpu_limit; - table[16].data = &c->disable_shm; + table[13].data = &c->dl_search_path; + table[14].data = &c->default_script_file; + table[15].data = c; + table[16].data = c; table[17].data = c; table[18].data = c; table[19].data = c; table[20].data = c; table[21].data = c; + table[22].data = c; + table[23].data = c; + table[24].data = c; #ifdef HAVE_SYS_RESOURCE_H - table[22].data = &c->rlimit_as; - table[23].data = &c->rlimit_core; - table[24].data = &c->rlimit_data; - table[25].data = &c->rlimit_fsize; - table[26].data = &c->rlimit_nofile; - table[27].data = &c->rlimit_stack; + table[25].data = &c->rlimit_as; + table[26].data = &c->rlimit_core; + table[27].data = &c->rlimit_data; + table[28].data = &c->rlimit_fsize; + table[29].data = &c->rlimit_nofile; + table[30].data = &c->rlimit_stack; #ifdef RLIMIT_NPROC - table[28].data = &c->rlimit_nproc; + table[31].data = &c->rlimit_nproc; #endif #ifdef RLIMIT_MEMLOCK #ifndef RLIMIT_NPROC #error "Houston, we have a numbering problem!" #endif - table[29].data = &c->rlimit_memlock; + table[32].data = &c->rlimit_memlock; +#endif +#ifdef RLIMIT_NICE +#ifndef RLIMIT_MEMLOCK +#error "Houston, we have a numbering problem!" +#endif + table[33].data = &c->rlimit_nice; +#endif +#ifdef RLIMIT_RTPRIO +#ifndef RLIMIT_NICE +#error "Houston, we have a numbering problem!" +#endif + table[34].data = &c->rlimit_rtprio; #endif #endif @@ -474,10 +544,17 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_assert(c->log_level <= PA_LOG_LEVEL_MAX); - pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize); - pa_strbuf_printf(s, "fail = %i\n", !!c->fail); - pa_strbuf_printf(s, "high-priority = %i\n", !!c->high_priority); - pa_strbuf_printf(s, "disallow-module-loading = %i\n", !!c->disallow_module_loading); + pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize)); + pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail)); + pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority)); + pa_strbuf_printf(s, "nice-level = %i\n", c->nice_level); + pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling)); + pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority); + pa_strbuf_printf(s, "disallow-module-loading = %s\n", pa_yes_no(c->disallow_module_loading)); + pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file)); + pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance)); + pa_strbuf_printf(s, "no-cpu-limit = %s\n", pa_yes_no(c->no_cpu_limit)); + pa_strbuf_printf(s, "disable-shm = %s\n", pa_yes_no(c->disable_shm)); pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time); pa_strbuf_printf(s, "module-idle-time = %i\n", c->module_idle_time); pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time); @@ -486,10 +563,6 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); - pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file); - pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance); - pa_strbuf_printf(s, "no-cpu-limit = %i\n", !!c->no_cpu_limit); - pa_strbuf_printf(s, "disable-shm = %i\n", !!c->disable_shm); pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format)); pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate); pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels); @@ -508,6 +581,12 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { #ifdef RLIMIT_MEMLOCK pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1); #endif +#ifdef RLIMIT_NICE + pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_nice.value : -1); +#endif +#ifdef RLIMIT_RTPRIO + pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_rtprio.value : -1); +#endif #endif return pa_strbuf_tostring_free(s); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index 4d37861d..b8930bd7 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -26,6 +26,7 @@ ***/ #include +#include #include #ifdef HAVE_SYS_RESOURCE_H @@ -48,29 +49,32 @@ typedef enum pa_daemon_conf_cmd { #ifdef HAVE_SYS_RESOURCE_H typedef struct pa_rlimit { rlim_t value; - int is_set; + pa_bool_t is_set; } pa_rlimit; #endif /* A structure containing configuration data for the PulseAudio server . */ typedef struct pa_daemon_conf { pa_daemon_conf_cmd_t cmd; - int daemonize, + pa_bool_t daemonize, fail, high_priority, + realtime_scheduling, disallow_module_loading, - exit_idle_time, - module_idle_time, - scache_idle_time, - auto_log_target, use_pid_file, system_instance, no_cpu_limit, disable_shm; + int exit_idle_time, + module_idle_time, + scache_idle_time, + auto_log_target, + realtime_priority, + nice_level, + resample_method; char *script_commands, *dl_search_path, *default_script_file; pa_log_target_t log_target; pa_log_level_t log_level; - int resample_method; char *config_file; #ifdef HAVE_SYS_RESOURCE_H @@ -81,6 +85,12 @@ typedef struct pa_daemon_conf { #ifdef RLIMIT_MEMLOCK pa_rlimit rlimit_memlock; #endif +#ifdef RLIMIT_NICE + pa_rlimit rlimit_nice; +#endif +#ifdef RLIMIT_RTPRIO + pa_rlimit rlimit_rtprio; +#endif #endif unsigned default_n_fragments, default_fragment_size_msec; diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 2132bf3d..54acd8ea 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -20,42 +20,58 @@ ## Configuration file for the pulseaudio daemon. Default values are ## commented out. Use either ; or # for commenting -# Extra verbositiy -; verbose = 0 - ## Daemonize after startup -; daemonize = 0 +; daemonize = no ## Quit if startup fails -; fail = 1 - -## Renice the daemon to level -15 and try to get SCHED_FIFO -## scheduling. This a good idea if you hear annyoing noise in the -## playback. However, this is a certain security issue, since it works -## when called SUID root only. root is dropped immediately after gaining -## the nice level and SCHED_FIFO scheduling on startup. -; high-priority = 0 +; fail = yes + +## Renice the daemon to level -15. This a good idea if you experience +## drop-outs in the playback. However, this is a certain security +## issue, since it works when called SUID root only. root is dropped +## immediately after gaining the nice level on startup, thus it is +## presumably safe. +; high-priority = yes + +## Try to acquire SCHED_FIFO scheduling for the IO threads. The same +## security concerns as mentioned above apply. However, if PA enters +## an endless loop, realtime scheduling causes a system lockup. Thus, +## realtime scheduling should only be enabled on trusted machines for +## now. Please not that only the IO threads of PulseAudio are made +## real-time. The controlling thread is left a normally scheduled +## thread. Thus the enabling the high-priority option is orthogonal. +; realtime-scheduling = no + +## The realtime priority to acquire, if realtime-scheduling is +## enabled. (Note: JACK uses 10 by default, 9 for clients -- some +## PulseAudio threads might choose a priority a little lower or higher +## than this value.) +; realtime-priority = 5 + +## The nice level to acquire for the daemon, if high-priority is +## enabled. (Note: on some distributions X11 uses -10 by default.) +; nice-level = -11 ## Disallow module loading after startup -; disallow-module-loading = 0 +; disallow-module-loading = no ## Terminate the daemon after the last client quit and this time ## passed. Use a negative value to disable this feature. ; exit-idle-time = -1 -## Unload autoloaded modules after being idle for this time +## Unload autoloaded modules after being idle for this time ; module-idle-time = 20 -## Unload autoloaded sample cache entries after being idle for this time +## Unload autoloaded sample cache entries after being idle for this time ; scache-idle-time = 20 ## The path were to look for dynamic shared objects (DSOs aka ## plugins). You may specify more than one path seperated by -## colons. +## colons. ; dl-search-path = @PA_DLSEARCHPATH@ ## The default script file to load. Specify an empty string for not -## loading a default script file. The +## loading a default script file. The ; default-script-file = @PA_DEFAULT_CONFIG_FILE@ ## The default log target. Use either "stderr", "syslog" or @@ -63,31 +79,42 @@ ## true, otherwise to "stderr". ; log-target = auto +# Log level, one of debug, info, notice, warning, error. Log messages +# with a lower log level than specified here are not logged, +; log-level = notice + ## The resampling algorithm to use. Use one of src-sinc-best-quality, ## src-sinc-medium-quality, src-sinc-fastest, src-zero-order-hold, -## src-linear, trivial. See the documentation of libsamplerate for an -## explanation for the different methods. The method 'trivial' is the -## only algorithm implemented without usage of floating point -## numbers. If you're tight on CPU consider using this. On the other -## hand it has the worst quality of all. -; resample-method = sinc-fastest +## src-linear, trivial, speex-float-N, speex-fixed-N, ffmpeg. See the +## documentation of libsamplerate for an explanation for the different +## src- methods. The method 'trivial' is the most basic algorithm +## implemented. If you're tight on CPU consider using this. On the +## other hand it has the worst quality of them all. The speex +## resamplers take an integer quality setting in the range 0..9 +## (bad...good). They exist in two flavours: fixed and float. The +## former uses fixed point numbers, the latter relies on floating +## point numbers. On most desktop CPUs the float point resmapler is a +## lot faster, and it also offers slightly better quality. +; resample-method = speex-float-3 ## Create a PID file in /tmp/pulseaudio-$USER/pid. Of this is enabled ## you may use commands like "pulseaudio --kill" or "pulseaudio ## --check". If you are planning to start more than one pulseaudio ## process per user, you better disable this option since it ## effectively disables multiple instances. -; use-pid-file = 1 +; use-pid-file = yes ## Do not install the CPU load limit, even on platforms where it is -## supported. This option is useful when debugging/profiling +## supported. This option is useful when debugging/profiling ## PulseAudio to disable disturbing SIGXCPU signals. -; no-cpu-limit = 0 +; no-cpu-limit = no ## Run the daemon as system-wide instance, requires root priviliges -; system-instance = 0 +; system-instance = no -## Resource limits, see getrlimit(2) for more information +## Resource limits, see getrlimit(2) for more information. Set to -1 +## if PA shouldn't touch the resource limit. Not all resource limits +## are available on all operating systems. ; rlimit-as = -1 ; rlimit-core = -1 ; rlimit-data = -1 @@ -96,9 +123,11 @@ ; rlimit-stack = -1 ; rlimit-nproc = -1 ; rlimit-memlock = 16384 +; rlimit-nice = 31 +; rlimit-rtprio = 9 -## Disable shared memory data transfer -; disable-shm = 0 +## Disable shared memory data transfer +; disable-shm = no ## Default sample format ; default-sample-format = s16le diff --git a/src/daemon/main.c b/src/daemon/main.c index cd3cfcc8..249131e0 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -307,6 +307,12 @@ static void set_all_rlimits(const pa_daemon_conf *conf) { #ifdef RLIMIT_MEMLOCK set_one_rlimit(&conf->rlimit_memlock, RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK"); #endif +#ifdef RLIMIT_NICE + set_one_rlimit(&conf->rlimit_nice, RLIMIT_NICE, "RLIMIT_NICE"); +#endif +#ifdef RLIMIT_RTPRIO + set_one_rlimit(&conf->rlimit_rtprio, RLIMIT_RTPRIO, "RLIMIT_RTPRIO"); +#endif } #endif -- cgit