From 79ad4e63f691d1280dde2eb6521a1572c78d03ce Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Oct 2008 01:14:36 +0200 Subject: Make the shared memory segment size configurable This is useful only on systems where memory overcommit is not available or disabled. --- man/pulse-client.conf.5.xml.in | 9 +++++++++ man/pulse-daemon.conf.5.xml.in | 9 +++++++++ src/daemon/daemon-conf.c | 36 ++++++++++++++++++++---------------- src/daemon/daemon-conf.h | 1 + src/daemon/daemon.conf.in | 1 + src/daemon/main.c | 2 +- src/pulse/client-conf.c | 3 +++ src/pulse/client-conf.h | 1 + src/pulse/client.conf.in | 1 + src/pulse/context.c | 4 ++-- src/pulsecore/conf-parser.c | 18 ++++++++++++++++++ src/pulsecore/conf-parser.h | 3 ++- src/pulsecore/core.c | 8 ++++---- src/pulsecore/core.h | 2 +- src/pulsecore/memblock.c | 18 ++++++++++++++++-- src/pulsecore/memblock.h | 2 +- src/tests/envelope-test.c | 2 +- src/tests/mcalign-test.c | 2 +- src/tests/memblock-test.c | 6 +++--- src/tests/memblockq-test.c | 2 +- src/tests/mix-test.c | 2 +- src/tests/remix-test.c | 2 +- src/tests/resampler-test.c | 2 +- 23 files changed, 99 insertions(+), 37 deletions(-) diff --git a/man/pulse-client.conf.5.xml.in b/man/pulse-client.conf.5.xml.in index ae8de1f8..1d6f6fb4 100644 --- a/man/pulse-client.conf.5.xml.in +++ b/man/pulse-client.conf.5.xml.in @@ -97,6 +97,15 @@ USA. no.

+ +
diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in index ed158dfa..9d77abf0 100644 --- a/man/pulse-daemon.conf.5.xml.in +++ b/man/pulse-daemon.conf.5.xml.in @@ -151,6 +151,15 @@ USA. argument takes precedence.

+ +
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 77da3f7e..939b25d7 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -84,7 +84,8 @@ static const pa_daemon_conf default_conf = { .disable_shm = FALSE, .default_n_fragments = 4, .default_fragment_size_msec = 25, - .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 } + .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 }, + .shm_size = 0 #ifdef HAVE_SYS_RESOURCE_H ,.rlimit_fsize = { .value = 0, .is_set = FALSE }, .rlimit_data = { .value = 0, .is_set = FALSE }, @@ -429,6 +430,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "disable-remixing", pa_config_parse_bool, NULL }, { "disable-lfe-remixing", pa_config_parse_bool, NULL }, { "load-default-script-file", pa_config_parse_bool, NULL }, + { "shm-size-bytes", pa_config_parse_size, NULL }, #ifdef HAVE_SYS_RESOURCE_H { "rlimit-fsize", parse_rlimit, NULL }, { "rlimit-data", parse_rlimit, NULL }, @@ -494,65 +496,66 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[26].data = &c->disable_remixing; table[27].data = &c->disable_lfe_remixing; table[28].data = &c->load_default_script_file; + table[29].data = &c->shm_size; #ifdef HAVE_SYS_RESOURCE_H - table[29].data = &c->rlimit_fsize; - table[30].data = &c->rlimit_data; - table[31].data = &c->rlimit_stack; - table[32].data = &c->rlimit_as; - table[33].data = &c->rlimit_core; - table[34].data = &c->rlimit_nofile; - table[35].data = &c->rlimit_as; + table[30].data = &c->rlimit_fsize; + table[31].data = &c->rlimit_data; + table[32].data = &c->rlimit_stack; + table[33].data = &c->rlimit_as; + table[34].data = &c->rlimit_core; + table[35].data = &c->rlimit_nofile; + table[36].data = &c->rlimit_as; #ifdef RLIMIT_NPROC - table[36].data = &c->rlimit_nproc; + table[37].data = &c->rlimit_nproc; #endif #ifdef RLIMIT_MEMLOCK #ifndef RLIMIT_NPROC #error "Houston, we have a numbering problem!" #endif - table[37].data = &c->rlimit_memlock; + table[38].data = &c->rlimit_memlock; #endif #ifdef RLIMIT_LOCKS #ifndef RLIMIT_MEMLOCK #error "Houston, we have a numbering problem!" #endif - table[38].data = &c->rlimit_locks; + table[39].data = &c->rlimit_locks; #endif #ifdef RLIMIT_SIGPENDING #ifndef RLIMIT_LOCKS #error "Houston, we have a numbering problem!" #endif - table[39].data = &c->rlimit_sigpending; + table[40].data = &c->rlimit_sigpending; #endif #ifdef RLIMIT_MSGQUEUE #ifndef RLIMIT_SIGPENDING #error "Houston, we have a numbering problem!" #endif - table[40].data = &c->rlimit_msgqueue; + table[41].data = &c->rlimit_msgqueue; #endif #ifdef RLIMIT_NICE #ifndef RLIMIT_MSGQUEUE #error "Houston, we have a numbering problem!" #endif - table[41].data = &c->rlimit_nice; + table[42].data = &c->rlimit_nice; #endif #ifdef RLIMIT_RTPRIO #ifndef RLIMIT_NICE #error "Houston, we have a numbering problem!" #endif - table[42].data = &c->rlimit_rtprio; + table[43].data = &c->rlimit_rtprio; #endif #ifdef RLIMIT_RTTIME #ifndef RLIMIT_RTTIME #error "Houston, we have a numbering problem!" #endif - table[43].data = &c->rlimit_rttime; + table[44].data = &c->rlimit_rttime; #endif #endif @@ -670,6 +673,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels); pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments); pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec); + pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size); #ifdef HAVE_SYS_RESOURCE_H pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1); pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index 309a1428..90329268 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -111,6 +111,7 @@ typedef struct pa_daemon_conf { unsigned default_n_fragments, default_fragment_size_msec; pa_sample_spec default_sample_spec; + size_t shm_size; } pa_daemon_conf; /* Allocate a new structure and fill it with sane defaults */ diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index ea09fe09..4362e1c1 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -26,6 +26,7 @@ ; use-pid-file = yes ; system-instance = no ; disable-shm = no +; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB ; high-priority = yes ; nice-level = -11 diff --git a/src/daemon/main.c b/src/daemon/main.c index a9e8ed46..53f5d193 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -854,7 +854,7 @@ int main(int argc, char *argv[]) { pa_assert_se(mainloop = pa_mainloop_new()); - if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) { + if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) { pa_log(_("pa_core_new() failed.")); goto finish; } diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 739ef161..58d64642 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -61,6 +61,7 @@ static const pa_client_conf default_conf = { .disable_shm = FALSE, .cookie_file = NULL, .cookie_valid = FALSE, + .shm_size = 0 }; pa_client_conf *pa_client_conf_new(void) { @@ -99,6 +100,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { { "autospawn", pa_config_parse_bool, NULL }, { "cookie-file", pa_config_parse_string, NULL }, { "disable-shm", pa_config_parse_bool, NULL }, + { "shm-size-bytes", pa_config_parse_size, NULL }, { NULL, NULL, NULL }, }; @@ -110,6 +112,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { table[5].data = &c->autospawn; table[6].data = &c->cookie_file; table[7].data = &c->disable_shm; + table[8].data = &c->shm_size; if (filename) { diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index 699279aa..4eac467e 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -31,6 +31,7 @@ typedef struct pa_client_conf { pa_bool_t autospawn, disable_shm; uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; pa_bool_t cookie_valid; /* non-zero, when cookie is valid */ + size_t shm_size; } pa_client_conf; /* Create a new configuration data object and reset it to defaults */ diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in index 8339d651..579bcc20 100644 --- a/src/pulse/client.conf.in +++ b/src/pulse/client.conf.in @@ -30,3 +30,4 @@ ; cookie-file = ; disable-shm = no +; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB diff --git a/src/pulse/context.c b/src/pulse/context.c index 154e5faf..3145d9c8 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -174,10 +174,10 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char * pa_client_conf_load(c->conf, NULL); pa_client_conf_env(c->conf); - if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm))) { + if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm, c->conf->shm_size))) { if (!c->conf->disable_shm) - c->mempool = pa_mempool_new(FALSE); + c->mempool = pa_mempool_new(FALSE, c->conf->shm_size); if (!c->mempool) { context_free(c); diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index 6b0e1d56..58ceab91 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -166,6 +166,24 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, return 0; } +int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { + size_t *i = data; + uint32_t k; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atou(rvalue, &k) < 0) { + pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); + return -1; + } + + *i = (size_t) k; + return 0; +} + int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { int k; pa_bool_t *b = data; diff --git a/src/pulsecore/conf-parser.h b/src/pulsecore/conf-parser.h index 7eb1fae2..a5174fce 100644 --- a/src/pulsecore/conf-parser.h +++ b/src/pulsecore/conf-parser.h @@ -39,8 +39,9 @@ typedef struct pa_config_item { * NULL */ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata); -/* Generic parsers for integers, booleans and strings */ +/* Generic parsers for integers, size_t, booleans and strings */ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index bd956ae0..5761bbc7 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -66,7 +66,7 @@ static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t o static void core_free(pa_object *o); -pa_core* pa_core_new(pa_mainloop_api *m, int shared) { +pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) { pa_core* c; pa_mempool *pool; int j; @@ -74,14 +74,14 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { pa_assert(m); if (shared) { - if (!(pool = pa_mempool_new(shared))) { + if (!(pool = pa_mempool_new(shared, shm_size))) { pa_log_warn("failed to allocate shared memory pool. Falling back to a normal memory pool."); - shared = 0; + shared = FALSE; } } if (!shared) { - if (!(pool = pa_mempool_new(shared))) { + if (!(pool = pa_mempool_new(shared, shm_size))) { pa_log("pa_mempool_new() failed."); return NULL; } diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index fb4490f2..39559082 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -141,7 +141,7 @@ enum { PA_CORE_MESSAGE_MAX }; -pa_core* pa_core_new(pa_mainloop_api *m, int shared); +pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size); /* Check whether noone is connected to this core */ void pa_core_check_idle(pa_core *c); diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 6d12acdc..400a4e1e 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -680,8 +680,9 @@ static void memblock_replace_import(pa_memblock *b) { pa_mutex_unlock(seg->import->mutex); } -pa_mempool* pa_mempool_new(pa_bool_t shared) { +pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size) { pa_mempool *p; + char t1[64], t2[64]; p = pa_xnew(pa_mempool, 1); @@ -692,13 +693,26 @@ pa_mempool* pa_mempool_new(pa_bool_t shared) { if (p->block_size < PA_PAGE_SIZE) p->block_size = PA_PAGE_SIZE; - p->n_blocks = PA_MEMPOOL_SLOTS_MAX; + if (size <= 0) + p->n_blocks = PA_MEMPOOL_SLOTS_MAX; + else { + p->n_blocks = (unsigned) (size / p->block_size); + + if (p->n_blocks < 2) + p->n_blocks = 2; + } if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) { pa_xfree(p); return NULL; } + pa_log_debug("Using %s memory pool with %u slots of size %s each, total size is %s", + p->memory.shared ? "shared" : "private", + p->n_blocks, + pa_bytes_snprint(t1, sizeof(t1), (unsigned) p->block_size), + pa_bytes_snprint(t2, sizeof(t2), (unsigned) (p->n_blocks * p->block_size))); + memset(&p->stat, 0, sizeof(p->stat)); pa_atomic_store(&p->n_init, 0); diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index efe55b02..b1eab2a9 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -117,7 +117,7 @@ pa_mempool * pa_memblock_get_pool(pa_memblock *b); pa_memblock *pa_memblock_will_need(pa_memblock *b); /* The memory block manager */ -pa_mempool* pa_mempool_new(pa_bool_t shared); +pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size); void pa_mempool_free(pa_mempool *p); const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p); void pa_mempool_vacuum(pa_mempool *p); diff --git a/src/tests/envelope-test.c b/src/tests/envelope-test.c index d71eff1c..4a72f5a3 100644 --- a/src/tests/envelope-test.c +++ b/src/tests/envelope-test.c @@ -205,7 +205,7 @@ int main(int argc, char *argv[]) { oil_init(); pa_log_set_maximal_level(PA_LOG_DEBUG); - pa_assert_se(pool = pa_mempool_new(FALSE)); + pa_assert_se(pool = pa_mempool_new(FALSE, 0)); pa_assert_se(envelope = pa_envelope_new(&ss)); block = generate_block(pool, &ss); diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index c0665822..92e3e14e 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) { pa_mcalign *a; pa_memchunk c; - p = pa_mempool_new(0); + p = pa_mempool_new(FALSE, 0); a = pa_mcalign_new(11); diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c index 6da1b1e9..37b5b403 100644 --- a/src/tests/memblock-test.c +++ b/src/tests/memblock-test.c @@ -78,9 +78,9 @@ int main(int argc, char *argv[]) { const char txt[] = "This is a test!"; - pool_a = pa_mempool_new(1); - pool_b = pa_mempool_new(1); - pool_c = pa_mempool_new(1); + pool_a = pa_mempool_new(TRUE, 0); + pool_b = pa_mempool_new(TRUE, 0); + pool_c = pa_mempool_new(TRUE, 0); pa_mempool_get_shm_id(pool_a, &id_a); pa_mempool_get_shm_id(pool_b, &id_b); diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c index 7bf992a1..c53945b4 100644 --- a/src/tests/memblockq-test.c +++ b/src/tests/memblockq-test.c @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) { pa_log_set_maximal_level(PA_LOG_DEBUG); - p = pa_mempool_new(0); + p = pa_mempool_new(FALSE, 0); silence.memblock = pa_memblock_new_fixed(p, (char*) "__", 2, 1); assert(silence.memblock); diff --git a/src/tests/mix-test.c b/src/tests/mix-test.c index 544121fd..759d7690 100644 --- a/src/tests/mix-test.c +++ b/src/tests/mix-test.c @@ -201,7 +201,7 @@ int main(int argc, char *argv[]) { oil_init(); pa_log_set_maximal_level(PA_LOG_DEBUG); - pa_assert_se(pool = pa_mempool_new(FALSE)); + pa_assert_se(pool = pa_mempool_new(FALSE, 0)); a.channels = 1; a.rate = 44100; diff --git a/src/tests/remix-test.c b/src/tests/remix-test.c index 4777c150..3538d7d4 100644 --- a/src/tests/remix-test.c +++ b/src/tests/remix-test.c @@ -58,7 +58,7 @@ int main(int argc, char *argv[]) { oil_init(); pa_log_set_maximal_level(PA_LOG_DEBUG); - pa_assert_se(pool = pa_mempool_new(FALSE)); + pa_assert_se(pool = pa_mempool_new(FALSE, 0)); for (i = 0; maps[i].channels > 0; i++) for (j = 0; maps[j].channels > 0; j++) { diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c index 6959127b..2d591867 100644 --- a/src/tests/resampler-test.c +++ b/src/tests/resampler-test.c @@ -201,7 +201,7 @@ int main(int argc, char *argv[]) { oil_init(); pa_log_set_maximal_level(PA_LOG_DEBUG); - pa_assert_se(pool = pa_mempool_new(FALSE)); + pa_assert_se(pool = pa_mempool_new(FALSE, 0)); a.channels = b.channels = 1; a.rate = b.rate = 44100; -- cgit