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.
This commit is contained in:
H.J. Lu 2020-06-01 14:11:32 -07:00
parent c670278934
commit dfb8e514cf
3 changed files with 82 additions and 8 deletions

View file

@ -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

View file

@ -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

View file

@ -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 **