From patchwork Wed May 10 14:47:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siddhesh Poyarekar X-Patchwork-Id: 20380 Received: (qmail 4020 invoked by alias); 10 May 2017 14:49:00 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 71914 invoked by uid 89); 10 May 2017 14:48:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_NEUTRAL autolearn=ham version=3.3.2 spammy=lifted, 1599, notable, Hx-languages-length:5178 X-HELO: homiemail-a58.g.dreamhost.com From: Siddhesh Poyarekar To: libc-alpha@sourceware.org Subject: [PATCH 3/8] tunables: Add support for tunables of uint64_t type Date: Wed, 10 May 2017 20:17:12 +0530 Message-Id: <1494427637-14555-4-git-send-email-siddhesh@sourceware.org> In-Reply-To: <1494427637-14555-1-git-send-email-siddhesh@sourceware.org> References: <1494427637-14555-1-git-send-email-siddhesh@sourceware.org> Recognize the uint64_t type in addition to the current int32_t and size_t. This allows addition of tunables of uint64_t types. In addition to adding the uint64_t type, this patch also consolidates validation and reading of integer types in tunables. One notable change is that of overflow computation in tunables_strtoul. The function was lifted from __internal_strtoul, but it does not need the boundary condition check (i.e. result == ULONG_MAX) since it does not need to set errno. As a result the check can be simplified, which I have now done. * elf/dl-tunable-types.h (tunable_type_code_t): New type TUNABLE_TYPE_UINT_64. * elf/dl-tunables.c (tunables_strtoul): Return uint64_t. Simplify computation of overflow. (tunable_set_val_if_valid_range_signed, tunable_set_val_if_valid_range_unsigned): Remove and replace with this... (TUNABLE_SET_VAL_IF_VALID_RANGE): ... New macro. (tunable_initialize): Adjust. Add uint64_t support. (__tunable_set_val): Add uint64_t support. --- elf/dl-tunable-types.h | 1 + elf/dl-tunables.c | 94 +++++++++++++++++++++----------------------------- 2 files changed, 41 insertions(+), 54 deletions(-) diff --git a/elf/dl-tunable-types.h b/elf/dl-tunable-types.h index 37a4e80..1d516df 100644 --- a/elf/dl-tunable-types.h +++ b/elf/dl-tunable-types.h @@ -24,6 +24,7 @@ typedef enum { TUNABLE_TYPE_INT_32, + TUNABLE_TYPE_UINT_64, TUNABLE_TYPE_SIZE_T, TUNABLE_TYPE_STRING } tunable_type_code_t; diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c index ebf48bb..8d72e26 100644 --- a/elf/dl-tunables.c +++ b/elf/dl-tunables.c @@ -105,10 +105,10 @@ get_next_env (char **envp, char **name, size_t *namelen, char **val, /* A stripped down strtoul-like implementation for very early use. It does not set errno if the result is outside bounds because it gets called before errno may have been set up. */ -static unsigned long int +static uint64_t tunables_strtoul (const char *nptr) { - unsigned long int result = 0; + uint64_t result = 0; long int sign = 1; unsigned max_digit; @@ -144,7 +144,7 @@ tunables_strtoul (const char *nptr) while (1) { - unsigned long int digval; + int digval; if (*nptr >= '0' && *nptr <= '0' + max_digit) digval = *nptr - '0'; else if (base == 16) @@ -159,9 +159,8 @@ tunables_strtoul (const char *nptr) else break; - if (result > ULONG_MAX / base - || (result == ULONG_MAX / base && digval > ULONG_MAX % base)) - return ULONG_MAX; + if (result >= (UINT64_MAX - digval) / base) + return UINT64_MAX; result *= base; result += digval; ++nptr; @@ -170,68 +169,50 @@ tunables_strtoul (const char *nptr) return result * sign; } -/* Initialize the internal type if the value validates either using the - explicit constraints of the tunable or with the implicit constraints of its - type. */ -static void -tunable_set_val_if_valid_range_signed (tunable_t *cur, const char *strval, - int64_t default_min, int64_t default_max) -{ - int64_t val = (int64_t) tunables_strtoul (strval); - - int64_t min = cur->type.min; - int64_t max = cur->type.max; - - if (min == max) - { - min = default_min; - max = default_max; - } - - if (val >= min && val <= max) - { - cur->val.numval = val; - cur->strval = strval; - } -} - -static void -tunable_set_val_if_valid_range_unsigned (tunable_t *cur, const char *strval, - uint64_t default_min, uint64_t default_max) -{ - uint64_t val = (uint64_t) tunables_strtoul (strval); - - uint64_t min = cur->type.min; - uint64_t max = cur->type.max; - - if (min == max) - { - min = default_min; - max = default_max; - } - - if (val >= min && val <= max) - { - cur->val.numval = val; - cur->strval = strval; - } -} +#define TUNABLE_SET_VAL_IF_VALID_RANGE(__cur, __val, __type, __default_min, \ + __default_max) \ +({ \ + __type min = (__cur)->type.min; \ + __type max = (__cur)->type.max; \ + \ + if (min == max) \ + { \ + min = __default_min; \ + max = __default_max; \ + } \ + \ + if ((__type) (__val) >= min && (__type) (val) <= max) \ + { \ + (__cur)->val.numval = val; \ + (__cur)->strval = strval; \ + } \ +}) /* Validate range of the input value and initialize the tunable CUR if it looks good. */ static void tunable_initialize (tunable_t *cur, const char *strval) { + uint64_t val; + + if (cur->type.type_code != TUNABLE_TYPE_STRING) + val = tunables_strtoul (strval); + switch (cur->type.type_code) { case TUNABLE_TYPE_INT_32: { - tunable_set_val_if_valid_range_signed (cur, strval, INT32_MIN, INT32_MAX); + TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, int64_t, INT32_MIN, INT32_MAX); + break; + } + case TUNABLE_TYPE_UINT_64: + { + TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t, 0, UINT64_MAX); break; } case TUNABLE_TYPE_SIZE_T: { - tunable_set_val_if_valid_range_unsigned (cur, strval, 0, SIZE_MAX); + TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t, 0, SIZE_MAX); break; } case TUNABLE_TYPE_STRING: @@ -461,6 +442,11 @@ __tunable_set_val (tunable_id_t id, void *valp, tunable_callback_t callback) switch (cur->type.type_code) { + case TUNABLE_TYPE_UINT_64: + { + *((uint64_t *) valp) = (uint64_t) cur->val.numval; + break; + } case TUNABLE_TYPE_INT_32: { *((int32_t *) valp) = (int32_t) cur->val.numval;