Add confirm_conf option
If the confirm_conf option is set, when the program starts, each of the four malloc_conf strings will be printed, and each option will be printed when being set.
This commit is contained in:
parent
4c63b0e76a
commit
c92ac30601
@ -904,6 +904,23 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay",
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="opt.confirm_conf">
|
||||
<term>
|
||||
<mallctl>opt.confirm_conf</mallctl>
|
||||
(<type>bool</type>)
|
||||
<literal>r-</literal>
|
||||
</term>
|
||||
<listitem><para>Confirm-runtime-options-when-program-starts
|
||||
enabled/disabled. If true, the string specified via
|
||||
<option>--with-malloc-conf</option>, the string pointed to by the
|
||||
global variable <varname>malloc_conf</varname>, the <quote>name</quote>
|
||||
of the file referenced by the symbolic link named
|
||||
<filename class="symlink">/etc/malloc.conf</filename>, and the value of
|
||||
the environment variable <envar>MALLOC_CONF</envar>, will be printed in
|
||||
order. Then, each option being set will be individually printed. This
|
||||
option is disabled by default.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="opt.abort_conf">
|
||||
<term>
|
||||
<mallctl>opt.abort_conf</mallctl>
|
||||
|
@ -10,6 +10,7 @@ extern bool malloc_slow;
|
||||
/* Run-time options. */
|
||||
extern bool opt_abort;
|
||||
extern bool opt_abort_conf;
|
||||
extern bool opt_confirm_conf;
|
||||
extern const char *opt_junk;
|
||||
extern bool opt_junk_alloc;
|
||||
extern bool opt_junk_free;
|
||||
|
@ -81,6 +81,7 @@ CTL_PROTO(config_utrace)
|
||||
CTL_PROTO(config_xmalloc)
|
||||
CTL_PROTO(opt_abort)
|
||||
CTL_PROTO(opt_abort_conf)
|
||||
CTL_PROTO(opt_confirm_conf)
|
||||
CTL_PROTO(opt_metadata_thp)
|
||||
CTL_PROTO(opt_retain)
|
||||
CTL_PROTO(opt_dss)
|
||||
@ -304,6 +305,7 @@ static const ctl_named_node_t config_node[] = {
|
||||
static const ctl_named_node_t opt_node[] = {
|
||||
{NAME("abort"), CTL(opt_abort)},
|
||||
{NAME("abort_conf"), CTL(opt_abort_conf)},
|
||||
{NAME("confirm_conf"), CTL(opt_confirm_conf)},
|
||||
{NAME("metadata_thp"), CTL(opt_metadata_thp)},
|
||||
{NAME("retain"), CTL(opt_retain)},
|
||||
{NAME("dss"), CTL(opt_dss)},
|
||||
@ -1741,6 +1743,7 @@ CTL_RO_CONFIG_GEN(config_xmalloc, bool)
|
||||
|
||||
CTL_RO_NL_GEN(opt_abort, opt_abort, bool)
|
||||
CTL_RO_NL_GEN(opt_abort_conf, opt_abort_conf, bool)
|
||||
CTL_RO_NL_GEN(opt_confirm_conf, opt_confirm_conf, bool)
|
||||
CTL_RO_NL_GEN(opt_metadata_thp, metadata_thp_mode_names[opt_metadata_thp],
|
||||
const char *)
|
||||
CTL_RO_NL_GEN(opt_retain, opt_retain, bool)
|
||||
|
204
src/jemalloc.c
204
src/jemalloc.c
@ -43,6 +43,8 @@ bool opt_abort_conf =
|
||||
false
|
||||
#endif
|
||||
;
|
||||
/* Intentionally default off, even with debug builds. */
|
||||
bool opt_confirm_conf = false;
|
||||
const char *opt_junk =
|
||||
#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))
|
||||
"true"
|
||||
@ -929,30 +931,33 @@ malloc_slow_flag_init(void) {
|
||||
malloc_slow = (malloc_slow_flags != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
unsigned i;
|
||||
char buf[PATH_MAX + 1];
|
||||
const char *opts, *k, *v;
|
||||
size_t klen, vlen;
|
||||
/* Number of sources for initializing malloc_conf */
|
||||
#define MALLOC_CONF_NSOURCES 4
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
/* Get runtime configuration. */
|
||||
switch (i) {
|
||||
static const char *
|
||||
obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) {
|
||||
if (config_debug) {
|
||||
static unsigned read_source = 0;
|
||||
/*
|
||||
* Each source should only be read once, to minimize # of
|
||||
* syscalls on init.
|
||||
*/
|
||||
assert(read_source++ == which_source);
|
||||
}
|
||||
assert(which_source < MALLOC_CONF_NSOURCES);
|
||||
|
||||
const char *ret;
|
||||
switch (which_source) {
|
||||
case 0:
|
||||
opts = config_malloc_conf;
|
||||
ret = config_malloc_conf;
|
||||
break;
|
||||
case 1:
|
||||
if (je_malloc_conf != NULL) {
|
||||
/*
|
||||
* Use options that were compiled into the
|
||||
* program.
|
||||
*/
|
||||
opts = je_malloc_conf;
|
||||
/* Use options that were compiled into the program. */
|
||||
ret = je_malloc_conf;
|
||||
} else {
|
||||
/* No configuration specified. */
|
||||
buf[0] = '\0';
|
||||
opts = buf;
|
||||
ret = NULL;
|
||||
}
|
||||
break;
|
||||
case 2: {
|
||||
@ -968,14 +973,13 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
;
|
||||
|
||||
/*
|
||||
* Try to use the contents of the "/etc/malloc.conf"
|
||||
* symbolic link's name.
|
||||
* Try to use the contents of the "/etc/malloc.conf" symbolic
|
||||
* link's name.
|
||||
*/
|
||||
#ifndef JEMALLOC_READLINKAT
|
||||
linklen = readlink(linkname, buf, sizeof(buf) - 1);
|
||||
linklen = readlink(linkname, buf, PATH_MAX);
|
||||
#else
|
||||
linklen = readlinkat(AT_FDCWD, linkname, buf,
|
||||
sizeof(buf) - 1);
|
||||
linklen = readlinkat(AT_FDCWD, linkname, buf, PATH_MAX);
|
||||
#endif
|
||||
if (linklen == -1) {
|
||||
/* No configuration specified. */
|
||||
@ -985,7 +989,7 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
}
|
||||
#endif
|
||||
buf[linklen] = '\0';
|
||||
opts = buf;
|
||||
ret = buf;
|
||||
break;
|
||||
} case 3: {
|
||||
const char *envname =
|
||||
@ -996,26 +1000,71 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
#endif
|
||||
;
|
||||
|
||||
if ((opts = jemalloc_secure_getenv(envname)) != NULL) {
|
||||
if ((ret = jemalloc_secure_getenv(envname)) != NULL) {
|
||||
/*
|
||||
* Do nothing; opts is already initialized to
|
||||
* the value of the MALLOC_CONF environment
|
||||
* variable.
|
||||
* Do nothing; opts is already initialized to the value
|
||||
* of the MALLOC_CONF environment variable.
|
||||
*/
|
||||
} else {
|
||||
/* No configuration specified. */
|
||||
buf[0] = '\0';
|
||||
opts = buf;
|
||||
ret = NULL;
|
||||
}
|
||||
break;
|
||||
} default:
|
||||
not_reached();
|
||||
buf[0] = '\0';
|
||||
opts = buf;
|
||||
ret = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
|
||||
bool initial_call, const char *opts_cache[MALLOC_CONF_NSOURCES],
|
||||
char buf[PATH_MAX + 1]) {
|
||||
static const char *opts_explain[MALLOC_CONF_NSOURCES] = {
|
||||
"string specified via --with-malloc-conf",
|
||||
"string pointed to by the global variable malloc_conf",
|
||||
"\"name\" of the file referenced by the symbolic link named "
|
||||
"/etc/malloc.conf",
|
||||
"value of the environment variable MALLOC_CONF"
|
||||
};
|
||||
unsigned i;
|
||||
const char *opts, *k, *v;
|
||||
size_t klen, vlen;
|
||||
|
||||
for (i = 0; i < MALLOC_CONF_NSOURCES; i++) {
|
||||
/* Get runtime configuration. */
|
||||
if (initial_call) {
|
||||
opts_cache[i] = obtain_malloc_conf(i, buf);
|
||||
}
|
||||
opts = opts_cache[i];
|
||||
if (!initial_call && opt_confirm_conf) {
|
||||
malloc_printf(
|
||||
"<jemalloc>: malloc_conf #%u (%s): \"%s\"\n",
|
||||
i + 1, opts_explain[i], opts != NULL ? opts : "");
|
||||
}
|
||||
if (opts == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (*opts != '\0' && !malloc_conf_next(&opts, &k, &klen, &v,
|
||||
&vlen)) {
|
||||
|
||||
#define CONF_ERROR(msg, k, klen, v, vlen) \
|
||||
if (!initial_call) { \
|
||||
malloc_conf_error( \
|
||||
msg, k, klen, v, vlen); \
|
||||
cur_opt_valid = false; \
|
||||
}
|
||||
#define CONF_CONTINUE { \
|
||||
if (!initial_call && opt_confirm_conf \
|
||||
&& cur_opt_valid) { \
|
||||
malloc_printf("<jemalloc>: Set "\
|
||||
"conf value: %.*s:%.*s\n", \
|
||||
(int)klen, k, (int)vlen, v);\
|
||||
} \
|
||||
continue; \
|
||||
}
|
||||
#define CONF_MATCH(n) \
|
||||
(sizeof(n)-1 == klen && strncmp(n, k, klen) == 0)
|
||||
#define CONF_MATCH_VALUE(n) \
|
||||
@ -1027,11 +1076,10 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
} else if (CONF_MATCH_VALUE("false")) { \
|
||||
o = false; \
|
||||
} else { \
|
||||
malloc_conf_error( \
|
||||
"Invalid conf value", \
|
||||
CONF_ERROR("Invalid conf value",\
|
||||
k, klen, v, vlen); \
|
||||
} \
|
||||
continue; \
|
||||
CONF_CONTINUE; \
|
||||
}
|
||||
/*
|
||||
* One of the CONF_MIN macros below expands, in one of the use points,
|
||||
@ -1054,8 +1102,7 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
um = malloc_strtoumax(v, &end, 0); \
|
||||
if (get_errno() != 0 || (uintptr_t)end -\
|
||||
(uintptr_t)v != vlen) { \
|
||||
malloc_conf_error( \
|
||||
"Invalid conf value", \
|
||||
CONF_ERROR("Invalid conf value",\
|
||||
k, klen, v, vlen); \
|
||||
} else if (clip) { \
|
||||
if (check_min(um, (t)(min))) { \
|
||||
@ -1069,7 +1116,7 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
} else { \
|
||||
if (check_min(um, (t)(min)) || \
|
||||
check_max(um, (t)(max))) { \
|
||||
malloc_conf_error( \
|
||||
CONF_ERROR( \
|
||||
"Out-of-range " \
|
||||
"conf value", \
|
||||
k, klen, v, vlen); \
|
||||
@ -1077,7 +1124,7 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
o = (t)um; \
|
||||
} \
|
||||
} \
|
||||
continue; \
|
||||
CONF_CONTINUE; \
|
||||
}
|
||||
#define CONF_HANDLE_UNSIGNED(o, n, min, max, check_min, check_max, \
|
||||
clip) \
|
||||
@ -1095,18 +1142,17 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
l = strtol(v, &end, 0); \
|
||||
if (get_errno() != 0 || (uintptr_t)end -\
|
||||
(uintptr_t)v != vlen) { \
|
||||
malloc_conf_error( \
|
||||
"Invalid conf value", \
|
||||
CONF_ERROR("Invalid conf value",\
|
||||
k, klen, v, vlen); \
|
||||
} else if (l < (ssize_t)(min) || l > \
|
||||
(ssize_t)(max)) { \
|
||||
malloc_conf_error( \
|
||||
CONF_ERROR( \
|
||||
"Out-of-range conf value", \
|
||||
k, klen, v, vlen); \
|
||||
} else { \
|
||||
o = l; \
|
||||
} \
|
||||
continue; \
|
||||
CONF_CONTINUE; \
|
||||
}
|
||||
#define CONF_HANDLE_CHAR_P(o, n, d) \
|
||||
if (CONF_MATCH(n)) { \
|
||||
@ -1115,7 +1161,14 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
sizeof(o)-1; \
|
||||
strncpy(o, v, cpylen); \
|
||||
o[cpylen] = '\0'; \
|
||||
continue; \
|
||||
CONF_CONTINUE; \
|
||||
}
|
||||
|
||||
bool cur_opt_valid = true;
|
||||
|
||||
CONF_HANDLE_BOOL(opt_confirm_conf, "confirm_conf")
|
||||
if (initial_call) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CONF_HANDLE_BOOL(opt_abort, "abort")
|
||||
@ -1132,10 +1185,10 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
malloc_conf_error("Invalid conf value",
|
||||
CONF_ERROR("Invalid conf value",
|
||||
k, klen, v, vlen);
|
||||
}
|
||||
continue;
|
||||
CONF_CONTINUE;
|
||||
}
|
||||
CONF_HANDLE_BOOL(opt_retain, "retain")
|
||||
if (strncmp("dss", k, klen) == 0) {
|
||||
@ -1145,7 +1198,7 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
if (strncmp(dss_prec_names[i], v, vlen)
|
||||
== 0) {
|
||||
if (extent_dss_prec_set(i)) {
|
||||
malloc_conf_error(
|
||||
CONF_ERROR(
|
||||
"Error setting dss",
|
||||
k, klen, v, vlen);
|
||||
} else {
|
||||
@ -1157,10 +1210,10 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
malloc_conf_error("Invalid conf value",
|
||||
CONF_ERROR("Invalid conf value",
|
||||
k, klen, v, vlen);
|
||||
}
|
||||
continue;
|
||||
CONF_CONTINUE;
|
||||
}
|
||||
CONF_HANDLE_UNSIGNED(opt_narenas, "narenas", 1,
|
||||
UINT_MAX, CONF_CHECK_MIN, CONF_DONT_CHECK_MAX,
|
||||
@ -1178,14 +1231,14 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
if (err || bin_update_shard_size(
|
||||
bin_shard_sizes, size_start,
|
||||
size_end, nshards)) {
|
||||
malloc_conf_error(
|
||||
CONF_ERROR(
|
||||
"Invalid settings for "
|
||||
"bin_shards", k, klen, v,
|
||||
vlen);
|
||||
break;
|
||||
}
|
||||
} while (vlen_left > 0);
|
||||
continue;
|
||||
CONF_CONTINUE;
|
||||
}
|
||||
CONF_HANDLE_SSIZE_T(opt_dirty_decay_ms,
|
||||
"dirty_decay_ms", -1, NSTIME_SEC_MAX * KQU(1000) <
|
||||
@ -1198,7 +1251,7 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
CONF_HANDLE_BOOL(opt_stats_print, "stats_print")
|
||||
if (CONF_MATCH("stats_print_opts")) {
|
||||
init_opt_stats_print_opts(v, vlen);
|
||||
continue;
|
||||
CONF_CONTINUE;
|
||||
}
|
||||
if (config_fill) {
|
||||
if (CONF_MATCH("junk")) {
|
||||
@ -1219,11 +1272,11 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
opt_junk_alloc = false;
|
||||
opt_junk_free = true;
|
||||
} else {
|
||||
malloc_conf_error(
|
||||
"Invalid conf value", k,
|
||||
klen, v, vlen);
|
||||
CONF_ERROR(
|
||||
"Invalid conf value",
|
||||
k, klen, v, vlen);
|
||||
}
|
||||
continue;
|
||||
CONF_CONTINUE;
|
||||
}
|
||||
CONF_HANDLE_BOOL(opt_zero, "zero")
|
||||
}
|
||||
@ -1260,7 +1313,7 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
if (strncmp(percpu_arena_mode_names[i],
|
||||
v, vlen) == 0) {
|
||||
if (!have_percpu_arena) {
|
||||
malloc_conf_error(
|
||||
CONF_ERROR(
|
||||
"No getcpu support",
|
||||
k, klen, v, vlen);
|
||||
}
|
||||
@ -1270,10 +1323,10 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
malloc_conf_error("Invalid conf value",
|
||||
CONF_ERROR("Invalid conf value",
|
||||
k, klen, v, vlen);
|
||||
}
|
||||
continue;
|
||||
CONF_CONTINUE;
|
||||
}
|
||||
CONF_HANDLE_BOOL(opt_background_thread,
|
||||
"background_thread");
|
||||
@ -1299,13 +1352,12 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
sc_data, slab_start,
|
||||
slab_end, (int)pgs);
|
||||
} else {
|
||||
malloc_conf_error(
|
||||
"Invalid settings for "
|
||||
"slab_sizes", k, klen, v,
|
||||
vlen);
|
||||
CONF_ERROR("Invalid settings "
|
||||
"for slab_sizes",
|
||||
k, klen, v, vlen);
|
||||
}
|
||||
} while (!err && vlen_left > 0);
|
||||
continue;
|
||||
CONF_CONTINUE;
|
||||
}
|
||||
if (config_prof) {
|
||||
CONF_HANDLE_BOOL(opt_prof, "prof")
|
||||
@ -1334,7 +1386,7 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
vlen : sizeof(log_var_names) - 1);
|
||||
strncpy(log_var_names, v, cpylen);
|
||||
log_var_names[cpylen] = '\0';
|
||||
continue;
|
||||
CONF_CONTINUE;
|
||||
}
|
||||
}
|
||||
if (CONF_MATCH("thp")) {
|
||||
@ -1343,7 +1395,7 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
if (strncmp(thp_mode_names[i],v, vlen)
|
||||
== 0) {
|
||||
if (!have_madvise_huge) {
|
||||
malloc_conf_error(
|
||||
CONF_ERROR(
|
||||
"No THP support",
|
||||
k, klen, v, vlen);
|
||||
}
|
||||
@ -1353,13 +1405,14 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
malloc_conf_error("Invalid conf value",
|
||||
CONF_ERROR("Invalid conf value",
|
||||
k, klen, v, vlen);
|
||||
}
|
||||
continue;
|
||||
CONF_CONTINUE;
|
||||
}
|
||||
malloc_conf_error("Invalid conf pair", k, klen, v,
|
||||
vlen);
|
||||
CONF_ERROR("Invalid conf pair", k, klen, v, vlen);
|
||||
#undef CONF_ERROR
|
||||
#undef CONF_CONTINUE
|
||||
#undef CONF_MATCH
|
||||
#undef CONF_MATCH_VALUE
|
||||
#undef CONF_HANDLE_BOOL
|
||||
@ -1382,6 +1435,19 @@ malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
atomic_store_b(&log_init_done, true, ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
static void
|
||||
malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) {
|
||||
const char *opts_cache[MALLOC_CONF_NSOURCES] = {NULL, NULL, NULL, NULL};
|
||||
char buf[PATH_MAX + 1];
|
||||
|
||||
/* The first call only set the confirm_conf option and opts_cache */
|
||||
malloc_conf_init_helper(NULL, NULL, true, opts_cache, buf);
|
||||
malloc_conf_init_helper(sc_data, bin_shard_sizes, false, opts_cache,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#undef MALLOC_CONF_NSOURCES
|
||||
|
||||
static bool
|
||||
malloc_init_hard_needed(void) {
|
||||
if (malloc_initialized() || (IS_INITIALIZER && malloc_init_state ==
|
||||
|
@ -1065,6 +1065,7 @@ stats_general_print(emitter_t *emitter) {
|
||||
|
||||
OPT_WRITE_BOOL("abort")
|
||||
OPT_WRITE_BOOL("abort_conf")
|
||||
OPT_WRITE_BOOL("confirm_conf")
|
||||
OPT_WRITE_BOOL("retain")
|
||||
OPT_WRITE_CHAR_P("dss")
|
||||
OPT_WRITE_UNSIGNED("narenas")
|
||||
|
@ -159,6 +159,7 @@ TEST_BEGIN(test_mallctl_opt) {
|
||||
|
||||
TEST_MALLCTL_OPT(bool, abort, always);
|
||||
TEST_MALLCTL_OPT(bool, abort_conf, always);
|
||||
TEST_MALLCTL_OPT(bool, confirm_conf, always);
|
||||
TEST_MALLCTL_OPT(const char *, metadata_thp, always);
|
||||
TEST_MALLCTL_OPT(bool, retain, always);
|
||||
TEST_MALLCTL_OPT(const char *, dss, always);
|
||||
|
Loading…
Reference in New Issue
Block a user