aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-06-01 14:11:32 -0700
committerH.J. Lu <hjl.tools@gmail.com>2020-09-29 09:03:47 -0700
commitdfb8e514cf4d770a9ce4e7858a351b9a2893614d (patch)
treec6d59af2a286ae6a241c23ce26be7d97223741d3
parentc6702789344043fa998923c8f32ed0bdb2edfa9c (diff)
downloadglibc-dfb8e514cf4d770a9ce4e7858a351b9a2893614d.zip
glibc-dfb8e514cf4d770a9ce4e7858a351b9a2893614d.tar.gz
glibc-dfb8e514cf4d770a9ce4e7858a351b9a2893614d.tar.bz2
Set tunable value as well as min/max values
Some tunable values and their minimum/maximum values must be determinted at run-time. Add TUNABLE_SET_WITH_BOUNDS and TUNABLE_SET_WITH_BOUNDS_FULL to update tunable value together with minimum and maximum values. __tunable_set_val is updated to set tunable value as well as min/max values.
-rw-r--r--elf/dl-tunables.c45
-rw-r--r--elf/dl-tunables.h21
-rw-r--r--manual/README.tunables24
3 files changed, 82 insertions, 8 deletions
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index 26e6e26..2ba2844 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -100,8 +100,42 @@ get_next_env (char **envp, char **name, size_t *namelen, char **val,
} \
})
+#define TUNABLE_SET_BOUNDS_IF_VALID(__cur, __minp, __maxp, __type) \
+({ \
+ if (__minp != NULL) \
+ { \
+ /* MIN is specified. */ \
+ __type min = *((__type *) __minp); \
+ if (__maxp != NULL) \
+ { \
+ /* Both MIN and MAX are specified. */ \
+ __type max = *((__type *) __maxp); \
+ if (max >= min \
+ && max <= (__cur)->type.max \
+ && min >= (__cur)->type.min) \
+ { \
+ (__cur)->type.min = min; \
+ (__cur)->type.max = max; \
+ } \
+ } \
+ else if (min > (__cur)->type.min && min <= (__cur)->type.max) \
+ { \
+ /* Only MIN is specified. */ \
+ (__cur)->type.min = min; \
+ } \
+ } \
+ else if (__maxp != NULL) \
+ { \
+ /* Only MAX is specified. */ \
+ __type max = *((__type *) __maxp); \
+ if (max < (__cur)->type.max && max >= (__cur)->type.min) \
+ (__cur)->type.max = max; \
+ } \
+})
+
static void
-do_tunable_update_val (tunable_t *cur, const void *valp)
+do_tunable_update_val (tunable_t *cur, const void *valp,
+ const void *minp, const void *maxp)
{
uint64_t val;
@@ -112,16 +146,19 @@ do_tunable_update_val (tunable_t *cur, const void *valp)
{
case TUNABLE_TYPE_INT_32:
{
+ TUNABLE_SET_BOUNDS_IF_VALID (cur, minp, maxp, int64_t);
TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, int64_t);
break;
}
case TUNABLE_TYPE_UINT_64:
{
+ TUNABLE_SET_BOUNDS_IF_VALID (cur, minp, maxp, uint64_t);
TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t);
break;
}
case TUNABLE_TYPE_SIZE_T:
{
+ TUNABLE_SET_BOUNDS_IF_VALID (cur, minp, maxp, uint64_t);
TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t);
break;
}
@@ -153,15 +190,15 @@ tunable_initialize (tunable_t *cur, const char *strval)
cur->initialized = true;
valp = strval;
}
- do_tunable_update_val (cur, valp);
+ do_tunable_update_val (cur, valp, NULL, NULL);
}
void
-__tunable_set_val (tunable_id_t id, void *valp)
+__tunable_set_val (tunable_id_t id, void *valp, void *minp, void *maxp)
{
tunable_t *cur = &tunable_list[id];
- do_tunable_update_val (cur, valp);
+ do_tunable_update_val (cur, valp, minp, maxp);
}
#if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring
diff --git a/elf/dl-tunables.h b/elf/dl-tunables.h
index f05eb50..550b0cc 100644
--- a/elf/dl-tunables.h
+++ b/elf/dl-tunables.h
@@ -70,9 +70,10 @@ typedef struct _tunable tunable_t;
extern void __tunables_init (char **);
extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
-extern void __tunable_set_val (tunable_id_t, void *);
+extern void __tunable_set_val (tunable_id_t, void *, void *, void *);
rtld_hidden_proto (__tunables_init)
rtld_hidden_proto (__tunable_get_val)
+rtld_hidden_proto (__tunable_set_val)
/* Define TUNABLE_GET and TUNABLE_SET in short form if TOP_NAMESPACE and
TUNABLE_NAMESPACE are defined. This is useful shorthand to get and set
@@ -82,11 +83,18 @@ rtld_hidden_proto (__tunable_get_val)
TUNABLE_GET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __cb)
# define TUNABLE_SET(__id, __type, __val) \
TUNABLE_SET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __val)
+# define TUNABLE_SET_WITH_BOUNDS(__id, __type, __val, __min, __max) \
+ TUNABLE_SET_WITH_BOUNDS_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, \
+ __type, __val, __min, __max)
#else
# define TUNABLE_GET(__top, __ns, __id, __type, __cb) \
TUNABLE_GET_FULL (__top, __ns, __id, __type, __cb)
# define TUNABLE_SET(__top, __ns, __id, __type, __val) \
TUNABLE_SET_FULL (__top, __ns, __id, __type, __val)
+# define TUNABLE_SET_WITH_BOUNDS(__top, __ns, __id, __type, __val, \
+ __min, __max) \
+ TUNABLE_SET_WITH_BOUNDS_FULL (__top, __ns, __id, __type, __val, \
+ __min, __max)
#endif
/* Get and return a tunable value. If the tunable was set externally and __CB
@@ -103,7 +111,16 @@ rtld_hidden_proto (__tunable_get_val)
# define TUNABLE_SET_FULL(__top, __ns, __id, __type, __val) \
({ \
__tunable_set_val (TUNABLE_ENUM_NAME (__top, __ns, __id), \
- & (__type) {__val}); \
+ & (__type) {__val}, NULL, NULL); \
+})
+
+/* Set a tunable value together with min/max values. */
+# define TUNABLE_SET_WITH_BOUNDS_FULL(__top, __ns, __id, __type, __val, \
+ __min, __max) \
+({ \
+ __tunable_set_val (TUNABLE_ENUM_NAME (__top, __ns, __id), \
+ & (__type) {__val}, & (__type) {__min}, \
+ & (__type) {__max}); \
})
/* Namespace sanity for callback functions. Use this macro to keep the
diff --git a/manual/README.tunables b/manual/README.tunables
index f87a31a..fff6c2a 100644
--- a/manual/README.tunables
+++ b/manual/README.tunables
@@ -67,7 +67,7 @@ The list of allowed attributes are:
non-AT_SECURE subprocesses.
NONE: Read all the time.
-2. Use TUNABLE_GET/TUNABLE_SET to get and set tunables.
+2. Use TUNABLE_GET/TUNABLE_SET/TUNABLE_SET_WITH_BOUNDS to get and set tunables.
3. OPTIONAL: If tunables in a namespace are being used multiple times within a
specific module, set the TUNABLE_NAMESPACE macro to reduce the amount of
@@ -112,9 +112,29 @@ form of the macros as follows:
where 'glibc' is the top namespace, 'cpu' is the tunable namespace and the
remaining arguments are the same as the short form macros.
+The minimum and maximum values can updated together with the tunable value
+using:
+
+ TUNABLE_SET_WITH_BOUNDS (check, int32_t, val, min, max)
+
+where 'check' is the tunable name, 'int32_t' is the C type of the tunable,
+'val' is a value of same type, 'min' and 'max' are the minimum and maximum
+values of the tunable.
+
+To set the minimum and maximum values of tunables in a different namespace
+from that module, use the full form of the macros as follows:
+
+ val = TUNABLE_GET_FULL (glibc, cpu, hwcap_mask, uint64_t, NULL)
+
+ TUNABLE_SET_WITH_BOUNDS_FULL (glibc, cpu, hwcap_mask, uint64_t, val, min, max)
+
+where 'glibc' is the top namespace, 'cpu' is the tunable namespace and the
+remaining arguments are the same as the short form macros.
+
When TUNABLE_NAMESPACE is not defined in a module, TUNABLE_GET is equivalent to
TUNABLE_GET_FULL, so you will need to provide full namespace information for
-both macros. Likewise for TUNABLE_SET and TUNABLE_SET_FULL.
+both macros. Likewise for TUNABLE_SET, TUNABLE_SET_FULL,
+TUNABLE_SET_WITH_BOUNDS and TUNABLE_SET_WITH_BOUNDS_FULL.
** IMPORTANT NOTE **