]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Set tunable value as well as min/max values
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 1 Jun 2020 21:11:32 +0000 (14:11 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 29 Sep 2020 16:03:47 +0000 (09:03 -0700)
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.

elf/dl-tunables.c
elf/dl-tunables.h
manual/README.tunables

index 26e6e266120596b8041e2ce133d057f8dc7838a8..2ba28440751f3f9fa81d50b6dbf761edcd409c43 100644 (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
index f05eb50c2f7e1718550dcc04742b9335641e2150..550b0cc7f40589530e6ebac8f572cf737c3941fa 100644 (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
index f87a31a65e0a34554a179e91ba214230c49c35a7..fff6c2a87e98a6fbb9e43cce9902098ae15e91ac 100644 (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 **