Message ID | 20210329182520.323665-3-adhemerval.zanella@linaro.org |
---|---|
State | Dropped |
Headers |
Return-Path: <libc-alpha-bounces@sourceware.org> 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 E23E73850403; Mon, 29 Mar 2021 18:25:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E23E73850403 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1617042330; bh=a4LgcnWQEJ5nwvrv6nOt/lVY8gMV1Q6y8rTAW6WpPnw=; 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=JjeIkAqI1X6qth4alCMiJ2QEp3Pbu7gYEpYDP1aDae15CWJk1+ZNUMjxfJKq/g1dE MkIlIvMcHLSVryeCl9RqZtZS288YXgKW6UxEVzRblLDyIlNmF1FjfXUJovuN+gRBIa FJ4hNw8xfxybmnR67Sxy3E0Sp5VcRv4mw8MzsV+s= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qt1-x82c.google.com (mail-qt1-x82c.google.com [IPv6:2607:f8b0:4864:20::82c]) by sourceware.org (Postfix) with ESMTPS id D37553861030 for <libc-alpha@sourceware.org>; Mon, 29 Mar 2021 18:25:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org D37553861030 Received: by mail-qt1-x82c.google.com with SMTP id g24so10005856qts.6 for <libc-alpha@sourceware.org>; Mon, 29 Mar 2021 11:25:28 -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=a4LgcnWQEJ5nwvrv6nOt/lVY8gMV1Q6y8rTAW6WpPnw=; b=GA9f6r2au+QPn3ouJGbISOA9fToRriVn6f284YcGSeJARQv/aDFgxnuXEYwg8GAn/B u2hdsxNsmmTfvwF0D0jT1OswDwSDBVcZi7DXF1q2luh4jdDToi/S6genfcMj3+c8Tg+6 IKcIvEL9N5Z1Srrq9ll+B103KPhwnlGRQ44PWULyYZfB88fykQ8vFS54gq7jSFcOjMXG nUxC9S9qvMsgoWhPItIxzyPLmSINqtd1HoHq9ZpEL4t4ySt65mQglzNCslKExN0m94Zt 8vz/h1n8J2p7e16LC/jMRp7SbQppINl9POeEKuiqmcjE0fTnpK+tO/yK7/u8PBmcHJR4 2YmA== X-Gm-Message-State: AOAM5300kXQv8hnj566ViJcP+4erUeGoKALlWlyOxPsLreOfOWBdQ3of I3r7+2QYmqckEi4odvchPD/NgNw7WlQlrbk4 X-Google-Smtp-Source: ABdhPJwBFfNn6TOber8GI2mhYNCkOCG6BvWZufClSHJyX+iA1WTA8yP6AnoVrUyBh2Se24Td04KMIw== X-Received: by 2002:ac8:45d7:: with SMTP id e23mr23767748qto.107.1617042328282; Mon, 29 Mar 2021 11:25:28 -0700 (PDT) Received: from localhost.localdomain ([177.194.41.149]) by smtp.googlemail.com with ESMTPSA id o7sm14009565qkb.104.2021.03.29.11.25.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 29 Mar 2021 11:25:28 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH 3/4] linux: Use /sys/devices/system/cpu/possible on __get_nprocs_conf Date: Mon, 29 Mar 2021 15:25:19 -0300 Message-Id: <20210329182520.323665-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210329182520.323665-1-adhemerval.zanella@linaro.org> References: <20210329182520.323665-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.5 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.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 <libc-alpha.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/libc-alpha>, <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/libc-alpha/> List-Post: <mailto:libc-alpha@sourceware.org> List-Help: <mailto:libc-alpha-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/libc-alpha>, <mailto:libc-alpha-request@sourceware.org?subject=subscribe> From: Adhemerval Zanella via Libc-alpha <libc-alpha@sourceware.org> Reply-To: Adhemerval Zanella <adhemerval.zanella@linaro.org> Cc: crrodriguez@opensuse.org Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" <libc-alpha-bounces@sourceware.org> |
Series |
[1/4] Remove architecture specific sched_cpucount optimizations
|
|
Commit Message
Adhemerval Zanella Netto
March 29, 2021, 6:25 p.m. UTC
Instead of iterate over all the cpu in the sysfs folder. It consumes slight less resources on large system (which might require extra getdents call) and memory (a limited stack buffer instead a large malloced one for opendir). Checked on x86_64-linux-gnu, aarch64-linux-gnu, and powerpc64le-linux-gnu. --- sysdeps/unix/sysv/linux/getsysstats.c | 51 +++++++++++++++------------ 1 file changed, 29 insertions(+), 22 deletions(-)
Comments
Ping. On 29/03/2021 15:25, Adhemerval Zanella wrote: > Instead of iterate over all the cpu in the sysfs folder. It consumes > slight less resources on large system (which might require extra > getdents call) and memory (a limited stack buffer instead a large > malloced one for opendir). > > Checked on x86_64-linux-gnu, aarch64-linux-gnu, and > powerpc64le-linux-gnu. > --- > sysdeps/unix/sysv/linux/getsysstats.c | 51 +++++++++++++++------------ > 1 file changed, 29 insertions(+), 22 deletions(-) > > diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c > index f8a4a31d1b..5069951246 100644 > --- a/sysdeps/unix/sysv/linux/getsysstats.c > +++ b/sysdeps/unix/sysv/linux/getsysstats.c > @@ -17,7 +17,8 @@ > License along with the GNU C Library; if not, see > <https://www.gnu.org/licenses/>. */ > > -#include <dirent.h> > +#include <ctype.h> > +#include <intprops.h> > #include <not-cancel.h> > #include <scratch_buffer.h> > #include <stdio.h> > @@ -63,33 +64,39 @@ weak_alias (__get_nprocs, get_nprocs) > int > __get_nprocs_conf (void) > { > - /* XXX Here will come a test for the new system call. */ > + int result = 1; > > /* Try to use the sysfs filesystem. It has actual information about > online processors. */ > - DIR *dir = __opendir ("/sys/devices/system/cpu"); > - if (dir != NULL) > + int fd = __open64_nocancel ("/sys/devices/system/cpu/possible", O_RDONLY); > + if (fd != -1) > { > - int count = 0; > - struct dirent64 *d; > - > - while ((d = __readdir64 (dir)) != NULL) > - /* NB: the sysfs has d_type support. */ > - if (d->d_type == DT_DIR && strncmp (d->d_name, "cpu", 3) == 0) > - { > - char *endp; > - unsigned long int nr = strtoul (d->d_name + 3, &endp, 10); > - if (nr != ULONG_MAX && endp != d->d_name + 3 && *endp == '\0') > - ++count; > - } > - > - __closedir (dir); > - > - return count; > + /* The entry is in the form of '[cpuX]-[cpuY]'. */ > + char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1]; > + > + ssize_t n = __read_nocancel (fd, buf, sizeof (buf)); > + if (n > 0) > + { > + buf[n] = '\0'; > + > + /* Start on the right, to find highest node number. */ > + int m = 1; > + while (--n) > + { > + if ((buf[n] == ',') || (buf[n] == '-')) > + break; > + /* Ignore '\n' */ > + if (! isdigit (buf[n])) > + continue; > + result += (buf[n] - '0') * m; > + m *= 10; > + } > + } > + > + __close_nocancel (fd); > + return result + 1; > } > > - int result = 1; > - > #ifdef GET_NPROCS_CONF_PARSER > /* If we haven't found an appropriate entry return 1. */ > FILE *fp = fopen ("/proc/cpuinfo", "rce"); >
* Adhemerval Zanella via Libc-alpha: > + /* The entry is in the form of '[cpuX]-[cpuY]'. */ > + char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1]; > + > + ssize_t n = __read_nocancel (fd, buf, sizeof (buf)); > + if (n > 0) > + { > + buf[n] = '\0'; > + > + /* Start on the right, to find highest node number. */ > + int m = 1; > + while (--n) > + { > + if ((buf[n] == ',') || (buf[n] == '-')) > + break; > + /* Ignore '\n' */ > + if (! isdigit (buf[n])) > + continue; > + result += (buf[n] - '0') * m; > + m *= 10; > + } > + } > + > + __close_nocancel (fd); > + return result + 1; > } I think the /online and /possible files have the same layout, so you could use both. Is there a way to tell whether the two data sources (/possible and the count of the cpu%d directory entries) actually agree? I tried to make sense of the kernel sources but didn't succeed. Thanks, Florian
* Florian Weimer: > * Adhemerval Zanella via Libc-alpha: > >> + /* The entry is in the form of '[cpuX]-[cpuY]'. */ >> + char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1]; >> + >> + ssize_t n = __read_nocancel (fd, buf, sizeof (buf)); >> + if (n > 0) >> + { >> + buf[n] = '\0'; >> + >> + /* Start on the right, to find highest node number. */ >> + int m = 1; >> + while (--n) >> + { >> + if ((buf[n] == ',') || (buf[n] == '-')) >> + break; >> + /* Ignore '\n' */ >> + if (! isdigit (buf[n])) >> + continue; >> + result += (buf[n] - '0') * m; >> + m *= 10; >> + } >> + } >> + >> + __close_nocancel (fd); >> + return result + 1; >> } > > I think the /online and /possible files have the same layout, so you > could use both. Sorry, I meant to write: “so you could use *one parser for* both” Florian
On 05/05/2021 15:06, Florian Weimer wrote: > * Florian Weimer: > >> * Adhemerval Zanella via Libc-alpha: >> >>> + /* The entry is in the form of '[cpuX]-[cpuY]'. */ >>> + char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1]; >>> + >>> + ssize_t n = __read_nocancel (fd, buf, sizeof (buf)); >>> + if (n > 0) >>> + { >>> + buf[n] = '\0'; >>> + >>> + /* Start on the right, to find highest node number. */ >>> + int m = 1; >>> + while (--n) >>> + { >>> + if ((buf[n] == ',') || (buf[n] == '-')) >>> + break; >>> + /* Ignore '\n' */ >>> + if (! isdigit (buf[n])) >>> + continue; >>> + result += (buf[n] - '0') * m; >>> + m *= 10; >>> + } >>> + } >>> + >>> + __close_nocancel (fd); >>> + return result + 1; >>> } >> >> I think the /online and /possible files have the same layout, so you >> could use both. > > Sorry, I meant to write: “so you could use *one parser for* both” I am not following, the second patch in this set *removed* the /sys/devices/system/cpu/online parsing in favor of the sched_getaffinity. So now it only parses /sys/devices/system/cpu/possible and fallbacks to sched_getaffinity.
On 05/05/2021 14:54, Florian Weimer wrote: > * Adhemerval Zanella via Libc-alpha: > >> + /* The entry is in the form of '[cpuX]-[cpuY]'. */ >> + char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1]; >> + >> + ssize_t n = __read_nocancel (fd, buf, sizeof (buf)); >> + if (n > 0) >> + { >> + buf[n] = '\0'; >> + >> + /* Start on the right, to find highest node number. */ >> + int m = 1; >> + while (--n) >> + { >> + if ((buf[n] == ',') || (buf[n] == '-')) >> + break; >> + /* Ignore '\n' */ >> + if (! isdigit (buf[n])) >> + continue; >> + result += (buf[n] - '0') * m; >> + m *= 10; >> + } >> + } >> + >> + __close_nocancel (fd); >> + return result + 1; >> } > > I think the /online and /possible files have the same layout, so you > could use both. > > Is there a way to tell whether the two data sources (/possible and the > count of the cpu%d directory entries) actually agree? I tried to make > sense of the kernel sources but didn't succeed. I am not sure, but at least the /possible is properly documented as 'testing' (which should stable as indicated by own kernel documentation [1]) ABI [2]: What: /sys/devices/system/cpu/kernel_max /sys/devices/system/cpu/offline /sys/devices/system/cpu/online /sys/devices/system/cpu/possible /sys/devices/system/cpu/present Date: December 2008 Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org> Description: CPU topology files that describe kernel limits related to hotplug. Briefly: kernel_max: the maximum cpu index allowed by the kernel configuration. offline: cpus that are not online because they have been HOTPLUGGED off or exceed the limit of cpus allowed by the kernel configuration (kernel_max above). online: cpus that are online and being scheduled. possible: cpus that have been allocated resources and can be brought online if they are present. So I think we don't need to certify that directories entries do match /possible values. [1] https://github.com/torvalds/linux/tree/master/Documentation/ABI [2] https://github.com/torvalds/linux/blob/master/Documentation/ABI/testing/sysfs-devices-system-cpu
* Adhemerval Zanella via Libc-alpha: > On 05/05/2021 15:06, Florian Weimer wrote: >> * Florian Weimer: >> >>> * Adhemerval Zanella via Libc-alpha: >>> >>>> + /* The entry is in the form of '[cpuX]-[cpuY]'. */ >>>> + char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1]; >>>> + >>>> + ssize_t n = __read_nocancel (fd, buf, sizeof (buf)); >>>> + if (n > 0) >>>> + { >>>> + buf[n] = '\0'; >>>> + >>>> + /* Start on the right, to find highest node number. */ >>>> + int m = 1; >>>> + while (--n) >>>> + { >>>> + if ((buf[n] == ',') || (buf[n] == '-')) >>>> + break; >>>> + /* Ignore '\n' */ >>>> + if (! isdigit (buf[n])) >>>> + continue; >>>> + result += (buf[n] - '0') * m; >>>> + m *= 10; >>>> + } >>>> + } >>>> + >>>> + __close_nocancel (fd); >>>> + return result + 1; >>>> } >>> >>> I think the /online and /possible files have the same layout, so you >>> could use both. >> >> Sorry, I meant to write: “so you could use *one parser for* both” > > I am not following, the second patch in this set *removed* the > /sys/devices/system/cpu/online parsing in favor of the sched_getaffinity. > So now it only parses /sys/devices/system/cpu/possible and fallbacks > to sched_getaffinity. Oh, right. So you removed the old implementation and bring bug a slightly different new one. Got it. Thanks, Florian
On 06/05/2021 10:51, Florian Weimer wrote: > * Adhemerval Zanella via Libc-alpha: > >> On 05/05/2021 15:06, Florian Weimer wrote: >>> * Florian Weimer: >>> >>>> * Adhemerval Zanella via Libc-alpha: >>>> >>>>> + /* The entry is in the form of '[cpuX]-[cpuY]'. */ >>>>> + char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1]; >>>>> + >>>>> + ssize_t n = __read_nocancel (fd, buf, sizeof (buf)); >>>>> + if (n > 0) >>>>> + { >>>>> + buf[n] = '\0'; >>>>> + >>>>> + /* Start on the right, to find highest node number. */ >>>>> + int m = 1; >>>>> + while (--n) >>>>> + { >>>>> + if ((buf[n] == ',') || (buf[n] == '-')) >>>>> + break; >>>>> + /* Ignore '\n' */ >>>>> + if (! isdigit (buf[n])) >>>>> + continue; >>>>> + result += (buf[n] - '0') * m; >>>>> + m *= 10; >>>>> + } >>>>> + } >>>>> + >>>>> + __close_nocancel (fd); >>>>> + return result + 1; >>>>> } >>>> >>>> I think the /online and /possible files have the same layout, so you >>>> could use both. >>> >>> Sorry, I meant to write: “so you could use *one parser for* both” >> >> I am not following, the second patch in this set *removed* the >> /sys/devices/system/cpu/online parsing in favor of the sched_getaffinity. >> So now it only parses /sys/devices/system/cpu/possible and fallbacks >> to sched_getaffinity. > > Oh, right. So you removed the old implementation and bring bug a > slightly different new one. Got it. Right, are you ok with the patch then?
* Adhemerval Zanella via Libc-alpha: > On 06/05/2021 10:51, Florian Weimer wrote: >> * Adhemerval Zanella via Libc-alpha: >> >>> On 05/05/2021 15:06, Florian Weimer wrote: >>>> * Florian Weimer: >>>> >>>>> * Adhemerval Zanella via Libc-alpha: >>>>> >>>>>> + /* The entry is in the form of '[cpuX]-[cpuY]'. */ >>>>>> + char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1]; >>>>>> + >>>>>> + ssize_t n = __read_nocancel (fd, buf, sizeof (buf)); >>>>>> + if (n > 0) >>>>>> + { >>>>>> + buf[n] = '\0'; >>>>>> + >>>>>> + /* Start on the right, to find highest node number. */ >>>>>> + int m = 1; >>>>>> + while (--n) >>>>>> + { >>>>>> + if ((buf[n] == ',') || (buf[n] == '-')) >>>>>> + break; >>>>>> + /* Ignore '\n' */ >>>>>> + if (! isdigit (buf[n])) >>>>>> + continue; >>>>>> + result += (buf[n] - '0') * m; >>>>>> + m *= 10; >>>>>> + } >>>>>> + } >>>>>> + >>>>>> + __close_nocancel (fd); >>>>>> + return result + 1; >>>>>> } >>>>> >>>>> I think the /online and /possible files have the same layout, so you >>>>> could use both. >>>> >>>> Sorry, I meant to write: “so you could use *one parser for* both” >>> >>> I am not following, the second patch in this set *removed* the >>> /sys/devices/system/cpu/online parsing in favor of the sched_getaffinity. >>> So now it only parses /sys/devices/system/cpu/possible and fallbacks >>> to sched_getaffinity. >> >> Oh, right. So you removed the old implementation and bring bug a >> slightly different new one. Got it. > > Right, are you ok with the patch then? The new parser cannot handle gaps or ranges that do not start at 0, I think. The old parser could cope with that. The kernel data structures support gaps in the possible CPU mask. I don't know if they occur in practice, but firmware quirks in this area aren't exactly rare (e.g., single-socket systems which report hundreds of hot-pluggable CPU cores). Thanks, Florian
On 07/05/2021 08:07, Florian Weimer wrote: > * Adhemerval Zanella via Libc-alpha: > >> On 06/05/2021 10:51, Florian Weimer wrote: >>> * Adhemerval Zanella via Libc-alpha: >>> >>>> On 05/05/2021 15:06, Florian Weimer wrote: >>>>> * Florian Weimer: >>>>> >>>>>> * Adhemerval Zanella via Libc-alpha: >>>>>> >>>>>>> + /* The entry is in the form of '[cpuX]-[cpuY]'. */ >>>>>>> + char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1]; >>>>>>> + >>>>>>> + ssize_t n = __read_nocancel (fd, buf, sizeof (buf)); >>>>>>> + if (n > 0) >>>>>>> + { >>>>>>> + buf[n] = '\0'; >>>>>>> + >>>>>>> + /* Start on the right, to find highest node number. */ >>>>>>> + int m = 1; >>>>>>> + while (--n) >>>>>>> + { >>>>>>> + if ((buf[n] == ',') || (buf[n] == '-')) >>>>>>> + break; >>>>>>> + /* Ignore '\n' */ >>>>>>> + if (! isdigit (buf[n])) >>>>>>> + continue; >>>>>>> + result += (buf[n] - '0') * m; >>>>>>> + m *= 10; >>>>>>> + } >>>>>>> + } >>>>>>> + >>>>>>> + __close_nocancel (fd); >>>>>>> + return result + 1; >>>>>>> } >>>>>> >>>>>> I think the /online and /possible files have the same layout, so you >>>>>> could use both. >>>>> >>>>> Sorry, I meant to write: “so you could use *one parser for* both” >>>> >>>> I am not following, the second patch in this set *removed* the >>>> /sys/devices/system/cpu/online parsing in favor of the sched_getaffinity. >>>> So now it only parses /sys/devices/system/cpu/possible and fallbacks >>>> to sched_getaffinity. >>> >>> Oh, right. So you removed the old implementation and bring bug a >>> slightly different new one. Got it. >> >> Right, are you ok with the patch then? > > The new parser cannot handle gaps or ranges that do not start at 0, I > think. The old parser could cope with that. The kernel data structures > support gaps in the possible CPU mask. I don't know if they occur in > practice, but firmware quirks in this area aren't exactly rare (e.g., > single-socket systems which report hundreds of hot-pluggable CPU cores). Indeed I did not take this in consideration and it seems that using /possible is more complicated than just opendir the directory. And we will need to handle the possible unlikely issue of a truncated value from kernel, since the buffer is limited to PAGE_SIZE. I will drop this patch.
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c index f8a4a31d1b..5069951246 100644 --- a/sysdeps/unix/sysv/linux/getsysstats.c +++ b/sysdeps/unix/sysv/linux/getsysstats.c @@ -17,7 +17,8 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ -#include <dirent.h> +#include <ctype.h> +#include <intprops.h> #include <not-cancel.h> #include <scratch_buffer.h> #include <stdio.h> @@ -63,33 +64,39 @@ weak_alias (__get_nprocs, get_nprocs) int __get_nprocs_conf (void) { - /* XXX Here will come a test for the new system call. */ + int result = 1; /* Try to use the sysfs filesystem. It has actual information about online processors. */ - DIR *dir = __opendir ("/sys/devices/system/cpu"); - if (dir != NULL) + int fd = __open64_nocancel ("/sys/devices/system/cpu/possible", O_RDONLY); + if (fd != -1) { - int count = 0; - struct dirent64 *d; - - while ((d = __readdir64 (dir)) != NULL) - /* NB: the sysfs has d_type support. */ - if (d->d_type == DT_DIR && strncmp (d->d_name, "cpu", 3) == 0) - { - char *endp; - unsigned long int nr = strtoul (d->d_name + 3, &endp, 10); - if (nr != ULONG_MAX && endp != d->d_name + 3 && *endp == '\0') - ++count; - } - - __closedir (dir); - - return count; + /* The entry is in the form of '[cpuX]-[cpuY]'. */ + char buf[2 * INT_STRLEN_BOUND (unsigned int) + 1]; + + ssize_t n = __read_nocancel (fd, buf, sizeof (buf)); + if (n > 0) + { + buf[n] = '\0'; + + /* Start on the right, to find highest node number. */ + int m = 1; + while (--n) + { + if ((buf[n] == ',') || (buf[n] == '-')) + break; + /* Ignore '\n' */ + if (! isdigit (buf[n])) + continue; + result += (buf[n] - '0') * m; + m *= 10; + } + } + + __close_nocancel (fd); + return result + 1; } - int result = 1; - #ifdef GET_NPROCS_CONF_PARSER /* If we haven't found an appropriate entry return 1. */ FILE *fp = fopen ("/proc/cpuinfo", "rce");