From patchwork Mon Sep 6 18:11:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 44871 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 1F8C8385B804 for ; Mon, 6 Sep 2021 18:14:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1F8C8385B804 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1630952053; bh=Mi/RnxOS4M6cpx/qMPy/dGkMfg68RWWrDkfBqpkc+Vc=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=DIZfgwwR2LxwSIiaUh7ZTdg8YQp3klC8M7nSxlqpqf01H03XWYTl988TNJ9HbuiwY fULmutvOCfCiBTyVfXiwL/xJCL2oT243edy6IxyGaEK3MogeVc1ScvQRipZLR2MAoC 5VjT6bu9jMBL/F/Dv+ZXppg7nVSHRT4f7L0OR2gc= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qv1-xf29.google.com (mail-qv1-xf29.google.com [IPv6:2607:f8b0:4864:20::f29]) by sourceware.org (Postfix) with ESMTPS id 3CE27385BF80 for ; Mon, 6 Sep 2021 18:11:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3CE27385BF80 Received: by mail-qv1-xf29.google.com with SMTP id ew6so4388583qvb.5 for ; Mon, 06 Sep 2021 11:11:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Mi/RnxOS4M6cpx/qMPy/dGkMfg68RWWrDkfBqpkc+Vc=; b=U6fA/mP0UHiMpzQQZVRE4uicY9X8HWGNn5a+lk2Z04X8wljdDerkeHyKlR/hpx/ckH fUcibICCJupRQaWM7XjRrikXrdUu/eXPv26nSm43oI4K5mJNCPBThHKv3r2wlnpotqIP DjDTtJhzJWvoBLxGKLpV5e3WPd89vOWZDabpX+46hiqt5X2cD6h/0tLzbVxu9JCnHJpt dk25FHx8initTIP3SiI6vDLC0V1NFaqUtg8LhKOel9qndk4prdpOEmGsNfVF4/yHHhET wdOozkBjO7w/owY0gvoWI/njoo/Vw5kHgDUKI0W/ZjfzRPEVbWfcE0DUhNdmpQE6V3H7 VJRw== X-Gm-Message-State: AOAM530fKJwyNUQAJ90ZC3436eXEWiVhksrN+8ASMoplCHlr30/A/yFC ZUV+s7TviSs9W2jcyJxAV77CoXEJgjxuuA== X-Google-Smtp-Source: ABdhPJwgtKswaqGecdkWfBDLIOI2kjfHQKY+9kHmLVxJC0O6nq95lQvO2tUO5FQcBpvJ+ZCjs21bOg== X-Received: by 2002:ad4:442c:: with SMTP id e12mr13232023qvt.36.1630951901721; Mon, 06 Sep 2021 11:11:41 -0700 (PDT) Received: from birita.. ([2804:431:c7cb:733d:210:e147:8627:2d6]) by smtp.gmail.com with ESMTPSA id j23sm7175647qkl.65.2021.09.06.11.11.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Sep 2021 11:11:41 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH 3/3] linux: Revert the use of sched_getaffinity on get_nproc (BZ #28310) Date: Mon, 6 Sep 2021 15:11:33 -0300 Message-Id: <20210906181133.1401140-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210906181133.1401140-1-adhemerval.zanella@linaro.org> References: <20210906181133.1401140-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Reply-To: Adhemerval Zanella Cc: Florian Weimer , Nicolas Saenz Julienne Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" The use of sched_getaffinity on get_nproc and sysconf (_SC_NPROCESSORS_ONLN) done in 903bc7dcc2acafc40 (BZ #27645) breaks the top command in common hypervisor configurations and also other monitoring tools. The main issue using sched_getaffinity changed the symbols semantic from system-wide scope of online CPUs to per-process one (which can be changed with kernel cpusets or book parameters in VM). This patch reverts mostly of the 903bc7dcc2acafc40, with the exceptions: * No more cached values and atomic updates, since they are inherent racy. * No /proc/cpuinfo fallback, since /proc/stat is already used and it would require to revert more arch-specific code. * The alloca is replace with a static buffer of 1024 bytes. So the implementation first consult the sysfs, and fallbacks to procfs. Checked on x86_64-linux-gnu. --- sysdeps/unix/sysv/linux/getsysstats.c | 140 +++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 5 deletions(-) diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c index b9710f8319..a1f84c01e2 100644 --- a/sysdeps/unix/sysv/linux/getsysstats.c +++ b/sysdeps/unix/sysv/linux/getsysstats.c @@ -17,6 +17,8 @@ . */ #include +#include +#include #include #include #include @@ -29,7 +31,7 @@ #include int -__get_nprocs (void) +__get_nprocs_sched (void) { /* This cannot use malloc because it is used on malloc initialization. */ enum { max_num_cpus = 32768 }; @@ -48,14 +50,142 @@ __get_nprocs (void) atomics are needed). */ return 2; } -libc_hidden_def (__get_nprocs) -weak_alias (__get_nprocs, get_nprocs) + +static char * +next_line (int fd, char *const buffer, char **cp, char **re, + char *const buffer_end) +{ + char *res = *cp; + char *nl = memchr (*cp, '\n', *re - *cp); + if (nl == NULL) + { + if (*cp != buffer) + { + if (*re == buffer_end) + { + memmove (buffer, *cp, *re - *cp); + *re = buffer + (*re - *cp); + *cp = buffer; + + ssize_t n = __read_nocancel (fd, *re, buffer_end - *re); + if (n < 0) + return NULL; + + *re += n; + + nl = memchr (*cp, '\n', *re - *cp); + while (nl == NULL && *re == buffer_end) + { + /* Truncate too long lines. */ + *re = buffer + 3 * (buffer_end - buffer) / 4; + n = __read_nocancel (fd, *re, buffer_end - *re); + if (n < 0) + return NULL; + + nl = memchr (*re, '\n', n); + **re = '\n'; + *re += n; + } + } + else + nl = memchr (*cp, '\n', *re - *cp); + + res = *cp; + } + + if (nl == NULL) + nl = *re - 1; + } + + *cp = nl + 1; + assert (*cp <= *re); + + return res == *re ? NULL : res; +} + int -__get_nprocs_sched (void) +__get_nprocs (void) { - return __get_nprocs (); + enum { buffer_size = 1024 }; + char buffer[buffer_size]; + char *buffer_end = buffer + buffer_size; + char *cp = buffer_end; + char *re = buffer_end; + + const int flags = O_RDONLY | O_CLOEXEC; + /* This file contains comma-separated ranges. */ + int fd = __open_nocancel ("/sys/devices/system/cpu/online", flags); + char *l; + int result = 0; + if (fd != -1) + { + l = next_line (fd, buffer, &cp, &re, buffer_end); + if (l != NULL) + do + { + char *endp; + unsigned long int n = strtoul (l, &endp, 10); + if (l == endp) + { + result = 0; + break; + } + + unsigned long int m = n; + if (*endp == '-') + { + l = endp + 1; + m = strtoul (l, &endp, 10); + if (l == endp) + { + result = 0; + break; + } + } + + result += m - n + 1; + + l = endp; + if (l < re && *l == ',') + ++l; + } + while (l < re && *l != '\n'); + + __close_nocancel_nostatus (fd); + + if (result > 0) + return result; + } + + cp = buffer_end; + re = buffer_end; + + /* Default to an SMP system in case we cannot obtain an accurate + number. */ + result = 2; + + /* The /proc/stat format is more uniform, use it by default. */ + fd = __open_nocancel ("/proc/stat", flags); + if (fd != -1) + { + result = 0; + + while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) + /* The current format of /proc/stat has all the cpu* entries + at the front. We assume here that stays this way. */ + if (strncmp (l, "cpu", 3) != 0) + break; + else if (isdigit (l[3])) + ++result; + + __close_nocancel_nostatus (fd); + } + + return result; } +libc_hidden_def (__get_nprocs) +weak_alias (__get_nprocs, get_nprocs) /* On some architectures it is possible to distinguish between configured