<opt>no</opt>.</p>
</option>
+ <option>
+ <p><opt>shm-size-bytes=</opt> Sets the shared memory segment
+ size for clients, in bytes. If left unspecified or is set to 0
+ it will default to some system-specific default, usually 64
+ MiB. Please note that usually there is no need to change this
+ value, unless you are running an OS kernel that does not do
+ memory overcommit.</p>
+ </option>
+
</section>
<section name="Authors">
argument takes precedence.</p>
</option>
+ <option>
+ <p><opt>shm-size-bytes=</opt> Sets the shared memory segment
+ size for the daemon, in bytes. If left unspecified or is set to 0
+ it will default to some system-specific default, usually 64
+ MiB. Please note that usually there is no need to change this
+ value, unless you are running an OS kernel that does not do
+ memory overcommit.</p>
+ </option>
+
</section>
<section name="Scheduling">
.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 },
{ "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 },
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
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);
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 */
; 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
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;
}
.disable_shm = FALSE,
.cookie_file = NULL,
.cookie_valid = FALSE,
+ .shm_size = 0
};
pa_client_conf *pa_client_conf_new(void) {
{ "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 },
};
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) {
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 */
; cookie-file =
; disable-shm = no
+; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
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);
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;
* 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);
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;
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;
}
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);
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);
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);
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);
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);
pa_mcalign *a;
pa_memchunk c;
- p = pa_mempool_new(0);
+ p = pa_mempool_new(FALSE, 0);
a = pa_mcalign_new(11);
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);
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);
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;
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++) {
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;