From patchwork Tue Sep 29 14:54:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 40546 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EB1F03959E49; Tue, 29 Sep 2020 14:55:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EB1F03959E49 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1601391315; bh=Ek6wyq3ySf+0I/g6alhXq7srYEUXVzH2V1QC7K/mxc4=; h=References:In-Reply-To:Date:Subject:To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=We/RJFMQvdNRFkQMFefNBwGXAh3GK7MO+x39dTi3iPCQvgCw/pKiLfrmZxHd1GESa OxrtFGLF71Tbje1HSDnROv8UjIjSawIGdnp0j738ITVLncoXCO8I/iUTz4IFZbtmfT amBCuF260RWJjx8RSQomd267tZDWliFA4+8FlkcU= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-il1-x134.google.com (mail-il1-x134.google.com [IPv6:2607:f8b0:4864:20::134]) by sourceware.org (Postfix) with ESMTPS id 784A83959CBB; Tue, 29 Sep 2020 14:55:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 784A83959CBB Received: by mail-il1-x134.google.com with SMTP id y2so5201095ila.0; Tue, 29 Sep 2020 07:55:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=Ek6wyq3ySf+0I/g6alhXq7srYEUXVzH2V1QC7K/mxc4=; b=UEPeJ64nFeIfZJo5GKJrZYVP12s8OXWbeFv7RKnYH3+BSL/Y0fDfXgVqZkv6fl8Hv6 JTL+UKUO3ZnkxvI0uyVHlgC9P0ncLKXEABLd/ga0tLFbyOF6yc783SmPzIkdJ2ShqdeM Q3cCU49k7YIGrylYy9sig4EeiqjVqkxK4v7kUe0MfQCSlKCgiopzCxgBxbJ7gjhNwjwG BpVxMfO8K/XFkP9BtPS+NCku/qfeRY0CrOtBTBX/BmBhPtUx3fdwsHWCiywcpMG7olXX oESHUnxoTLgdgLR3Oa9BOBA0G0fekylhKqtpMDPGqtv8v1g3iiTJsT3gB9Y6yCvmBY0C XS9w== X-Gm-Message-State: AOAM531OGboN5WHcmc+8Npa6iQw4Di7Xn6CNZB2kElR8rQ+8HQfwGBcP CG1n+gSePMDpDGVadYKa7BygQekbktqe4p3DMvJ1+mDy4So= X-Google-Smtp-Source: ABdhPJyP4Xmskx8cHZVdTY4YpFVhzJezJRDkU4cpEqgFXXB/VFKNsdAEretXIRT4VI4TgLYXSgwZ7zcP1ar5Jh2S2ys= X-Received: by 2002:a05:6e02:d06:: with SMTP id g6mr3288715ilj.151.1601391310845; Tue, 29 Sep 2020 07:55:10 -0700 (PDT) MIME-Version: 1.0 References: <20200918160709.949608-1-hjl.tools@gmail.com> <20200918160709.949608-3-hjl.tools@gmail.com> <87eemm6n37.fsf@oldenburg2.str.redhat.com> <42e48ec7-4b11-387c-eaf0-50bc564dbca0@sourceware.org> <565f21f3-0630-2d4e-dff4-6cda90533fb5@gotplt.org> <8046ee6e-b0e9-405a-b266-3f28ad75165d@sourceware.org> In-Reply-To: <8046ee6e-b0e9-405a-b266-3f28ad75165d@sourceware.org> Date: Tue, 29 Sep 2020 07:54:35 -0700 Message-ID: Subject: V5 [PATCH] Set tunable value as well as min/max values To: Siddhesh Poyarekar X-Spam-Status: No, score=-3038.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Cc: Florian Weimer , "H.J. Lu via Libc-alpha" Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" On Tue, Sep 29, 2020 at 6:50 AM Siddhesh Poyarekar wrote: > > On 29/09/20 18:00, H.J. Lu wrote: > > Here is the updated patch with TUNABLE_SET_BOUNDS_IF_VALID. > > > > OK for master? > > I don't think TUNABLE_SET_BOUNDS_IF_VALID is doing what it intends to do. > > > +#define TUNABLE_SET_BOUNDS_IF_VALID(__cur, __maxp, __minp, __type) \ > > minp and maxp are switched around. Fixed. > > +({ \ > > + __type min = __minp ? *((__type *) __minp) : (__cur)->type.min; \ > > + __type max = __maxp ? *((__type *) __maxp) : (__cur)->type.max; \ > > + if (__minp) \ > > + { \ > > + if (__maxp) \ > > + { \ > > + if (max > min) \ > > + { \ > > + (__cur)->type.min = min; \ > > + (__cur)->type.max = max; \ > > + } \ > > When both minp and maxp are specified, it checks if they're sane with > respect to each other but it should also check whether the range they > describe is a *subset* of (__cur)->type.min and (__cur)->type.max. > > > + } \ > > + else if (max > min) \ > > + (__cur)->type.min = min; \ > > You also need to make sure that (__cur)->type.min < min to ensure a more > restrictive range. > > > + } \ > > + else if (max > min) \ > > + (__cur)->type.max = min; \ > > I did not understand this one. > > Basically, this is what it should look like: > > if (__minp != NULL > && *__minp <= *__maxp __maxp may be NULL. > && *__minp >= (__cur)->type.min > && *__minp <= (__cur)->type.max) > (__cur)->type.min = *__minp; > > if (__maxp != NULL > && *__minp <= *_maxp __minp may be NULL. > && *__maxp >= (__cur)->type.min > && *__maxp <= (__cur)->type.max) > (__cur)->type.max = *maxp; > > You could collapse some of these conditions if we assume that maxp and > minp are always either NULL or not NULL together. > I don't think we should make such assumptions. Here is the updated patch with the check for the subset of (__cur)->type.min and (__cur)->type.max. From 9dd6abbb94c1589f58b12c8dbb5159cc51e6b08e Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 1 Jun 2020 14:11:32 -0700 Subject: [PATCH] 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. --- elf/dl-tunables.c | 45 ++++++++++++++++++++++++++++++++++++++---- elf/dl-tunables.h | 21 ++++++++++++++++++-- manual/README.tunables | 24 ++++++++++++++++++++-- 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c index 26e6e26612..2ba2844075 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 f05eb50c2f..550b0cc7f4 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 f87a31a65e..fff6c2a87e 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 ** -- 2.26.2