@@ -264,7 +264,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
_dl_aux_init (auxvec);
# endif
- __tunables_init (__environ);
+ __tunables_init (__environ, argv);
ARCH_INIT_CPU_FEATURES ();
@@ -323,6 +323,7 @@ tests := \
tests-internal := \
$(tests-static-internal) \
tst-tls1 \
+ tst-tunconf1 \
# tests-internal
tests-static := $(tests-static-normal) $(tests-static-internal)
@@ -333,6 +334,8 @@ tests-static += \
tst-tls9-static \
# tests-static
+tst-tunconf1-ENV = GLIBC_TUNABLES=glibc.malloc.tcache_count=5
+
static-dlopen-environment = \
LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)dlfcn
tst-tls9-static-ENV = $(static-dlopen-environment)
@@ -532,6 +535,7 @@ tests-container += \
tst-pldd \
tst-preload-pthread-libc \
tst-rootdir \
+ tst-tunconf1 \
# tests-container
test-srcs = \
@@ -300,9 +300,10 @@ print_extensions (struct cache_extension_all_loaded *ext,
thc->signature, thc->version, thc->num_tunables);
for (i = 0; i < count; ++ i)
{
- printf(" [%d] %s : %s [flags 0x%08x",
+ printf(" [%d] %s (%d) : %s [flags 0x%08x",
i,
cache_data + tec[i].name_offset,
+ tec[i].tunable_id,
cache_data + tec[i].value_offset,
tec[i].flags);
if (tec[i].flag_offset != 0)
@@ -318,13 +318,15 @@ dl_strlen(const char *s)
ENV_ALIAS to find values. Later we will also use the tunable names to find
values. */
void
-__tunables_init (char **envp)
+__tunables_init (char **envp, char **argv)
{
char *envname = NULL;
char *envval = NULL;
char **prev_envp = envp;
-
#ifdef SHARED
+ const char *prog_name = (argv && argv[0]) ? argv[0] : "";
+ int prog_name_len = -1;
+
const struct tunable_header_cached *thc;
const char *td;
@@ -357,9 +359,31 @@ __tunables_init (char **envp)
if (tid == -1)
continue;
}
- /* At this point, TID is valid for the tunable we want. See
- if the parsed type matches the desired type. */
-
+ /* At this point, TID is valid for the tunable we want. */
+
+ /* Apply selected filter, if any. */
+ switch (tec->flags & TUNCONF_FLAG_FILTER) {
+ case TUNCONF_FILTER_PERPROC:
+ /* Perform one-time calculations that aren't needed if we
+ don't use this filter. */
+ if (prog_name_len == -1 && prog_name != NULL)
+ {
+ const char *slash = NULL, *cp;
+ for (cp = prog_name; *cp; ++ cp)
+ if (*cp == '/')
+ slash = cp;
+ if (slash)
+ prog_name = slash + 1;
+ prog_name_len = dl_strlen (prog_name);
+ }
+ if (memcmp (prog_name, td + tec->flag_offset, prog_name_len) != 0)
+ goto skip_due_to_filter;
+ break;
+ default:
+ break;
+ }
+
+ /* See if the parsed type matches the desired type. */
if (tunable_list[tid].type.type_code == TUNABLE_TYPE_STRING)
{
/* This is a memory leak but there's no easy way around
@@ -379,9 +403,11 @@ __tunables_init (char **envp)
else
{
tunable_initialize (& tunable_list[tid],
- value, dl_strlen(value));
+ value, dl_strlen (value));
}
}
+
+ skip_due_to_filter:
}
}
#endif
@@ -47,7 +47,7 @@ typedef void (*tunable_callback_t) (tunable_val_t *);
#include "dl-tunable-list.h"
-extern void __tunables_init (char **);
+extern void __tunables_init (char **, char **);
extern void __tunables_print (void);
extern bool __tunable_is_initialized (tunable_id_t);
extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
new file mode 100644
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+#include "dl-tunables.h"
+
+int
+main(void)
+{
+ printf("tst-tunconf1 !\n");
+ size_t tcache_count = TUNABLE_GET_FULL (glibc, malloc, tcache_count, size_t, NULL);
+ size_t tcache_max = TUNABLE_GET_FULL (glibc, malloc, tcache_max, size_t, NULL);
+ printf("tcache count is %ld (should be 5, from env)\n", (long)tcache_count);
+ printf("tcache max is %ld (should be 4, from /etc)\n", (long)tcache_max);
+
+
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,2 @@
+glibc.malloc.tcache_max=4
+glibc.malloc.tcache_count=3
new file mode 100644
new file mode 100644
@@ -65,12 +65,14 @@ typedef enum {
struct tunable_entry_int {
struct stringtable_entry *name;
struct stringtable_entry *value;
+ struct stringtable_entry *filter;
TOP top;
int tunable_id;
int value_is_negative:1;
int value_was_parsed:1;
unsigned long long value_ull;
signed long long value_sll;
+ long filter_flags;
struct tunable_entry_int *next;
};
@@ -78,11 +80,80 @@ struct tunable_entry_int {
struct tunable_entry_int *entry_list;
struct tunable_entry_int **entry_list_next = &entry_list;
+static int filter_flags = 0;
+static char *filter_string = NULL;
+
/*----------------------------------------------------------------------*/
static void parse_tunconf_include (const char *tunconfig_file, unsigned int lineno,
bool do_chroot, const char *pattern, const char *opt_chroot);
+
+static void
+clear_filter (void)
+{
+ free (filter_string);
+ filter_string = NULL;
+ filter_flags = 0;
+}
+
+/* Filters are lines the are bracketed, like
+ [prog:foo]
+*/
+static void
+parse_filter (char *line, const char *filename, int lineno)
+{
+ const char *colon = NULL;
+ const char *right_bracket = NULL;
+ const char *cp;
+
+ for (cp=line; *cp != 0; cp++)
+ {
+ if (*cp == ':')
+ colon = cp;
+ if (*cp == ']')
+ {
+ right_bracket = cp;
+ break;
+ }
+ }
+ /* Special case: [] means "no filter" */
+ if (right_bracket != NULL && right_bracket == line + 1)
+ {
+ clear_filter ();
+ return;
+ }
+ if (colon == NULL)
+ {
+ printf("%s:%d: syntax error, filter line ignored: `%s' (missing ':')\n",
+ filename, lineno, line);
+ return;
+ }
+ if (right_bracket == NULL)
+ {
+ printf("%s:%d: syntax error, filter line ignored: `%s' (missing ']')\n",
+ filename, lineno, line);
+ return;
+ }
+
+ if (filter_string != NULL)
+ {
+ clear_filter ();
+ }
+
+ if (memcmp ("proc", line + 1, colon - line - 1) == 0)
+ {
+ filter_string = (char *) malloc (right_bracket - colon);
+ memcpy (filter_string, colon + 1, right_bracket - colon - 1);
+ filter_string [right_bracket - colon] = 0;
+ filter_flags = TUNCONF_FILTER_PERPROC;
+ }
+
+ else
+ printf("%s:%d: unrecognized filter `%.*s', ignored\n", filename, lineno, (int)(colon - line - 1), line + 1);
+}
+
+
static void
add_tunable (char *line, const char *filename, int lineno)
{
@@ -95,11 +166,10 @@ add_tunable (char *line, const char *filename, int lineno)
int i, id;
orig_line = line;
- printf("%s:%d: `%s'\n", filename, lineno, line);
// Leading whitespace has already been stripped.
- if (*line == '!' || *line == '+' || *line == '-')
+ if (*line == '!' || *line == '+' || *line == '-' || *line == '[')
{
switch (*line)
{
@@ -112,8 +182,10 @@ add_tunable (char *line, const char *filename, int lineno)
case '-':
top = TOP_DENY;
break;
+ case '[':
+ parse_filter (line, filename, lineno);
+ return;
}
- printf("TOP: %d\n", top);
line ++;
while (*line && isspace(*line))
line ++;
@@ -177,6 +249,12 @@ add_tunable (char *line, const char *filename, int lineno)
entry->tunable_id = id;
entry->top = top;
+ if (filter_flags)
+ {
+ entry->filter_flags = filter_flags;
+ entry->filter = cache_store_string (filter_string);
+ }
+
*entry_list_next = entry;
entry_list_next = & (entry->next);
}
@@ -190,6 +268,9 @@ parse_tunconf (const char *filename, int do_chroot, char *opt_chroot)
size_t len = 0;
unsigned int lineno;
+ /* Filters do not live across file boundaries. */
+ clear_filter ();
+
if (do_chroot && opt_chroot)
{
canon = chroot_canon (opt_chroot, filename);
@@ -261,6 +342,7 @@ Warning: ignoring configuration file that cannot be opened: %s"),
/* Free buffer and close file. */
free (line);
fclose (file);
+ clear_filter ();
}
/* Handle one word in an `include' line, a glob pattern of additional
@@ -392,7 +474,15 @@ get_tunconf_ext (uint32_t string_table_offset)
tec->tunable_id = tei->tunable_id;
tec->name_offset = tei->name->offset + string_table_offset;
tec->value_offset = tei->value->offset + string_table_offset;
- tec->flag_offset = 0;
+
+ if (tei->filter_flags != 0)
+ {
+ tec->flag_offset = tei->filter->offset + string_table_offset;
+ tec->flags |= tei->filter_flags;
+ }
+ else
+ tec->flag_offset = 0;
+
tec->unused_1 = 0;
if (tei->value_is_negative)
tec->parsed_value = (uint64_t) tei->value_sll;
@@ -99,7 +99,7 @@ _dl_sysdep_start (void **start_argptr,
__libc_enable_secure = _dl_hurd_data->flags & EXEC_SECURE;
- __tunables_init (_environ);
+ __tunables_init (_environ, _dl_argv);
/* Initialize DSO sorting algorithm after tunables. */
_dl_sort_maps_init ();
@@ -108,7 +108,7 @@ _dl_sysdep_start (void **start_argptr,
dl_hwcap_check ();
- __tunables_init (_environ);
+ __tunables_init (_environ, (char **) (start_argptr + 1));
/* Initialize DSO sorting algorithm after tunables. */
_dl_sort_maps_init ();