From f43b4be6556daf9d406bca5d3cfe4e6722ef02c7 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 15 Feb 2009 23:43:36 +0000 Subject: [PATCH] * sysdeps/unix/sysv/linux/getsysstats.c (next_line): New function. (GET_NPROCS_PARSER): Change parameters and use next_line. (__get_nprocs): Rewrite to not use stdio routines. * sysdeps/unix/sysv/linux/sparc/getsysstats.c (GET_NPROCS_PARSER): Change parameters and use next_line. --- ChangeLog | 8 +++ sysdeps/unix/sysv/linux/getsysstats.c | 85 ++++++++++++++++++++++------- sysdeps/unix/sysv/linux/sparc/getsysstats.c | 9 +-- 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9293d21..57e3777 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-02-15 Ulrich Drepper + + * sysdeps/unix/sysv/linux/getsysstats.c (next_line): New function. + (GET_NPROCS_PARSER): Change parameters and use next_line. + (__get_nprocs): Rewrite to not use stdio routines. + * sysdeps/unix/sysv/linux/sparc/getsysstats.c (GET_NPROCS_PARSER): + Change parameters and use next_line. + 2009-02-13 Ulrich Drepper [BZ #5381] diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c index 6d4c9c0..28f52c0 100644 --- a/sysdeps/unix/sysv/linux/getsysstats.c +++ b/sysdeps/unix/sysv/linux/getsysstats.c @@ -1,5 +1,5 @@ /* Determine various system internal values, Linux version. - Copyright (C) 1996-2001, 2002, 2003, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1996-2003, 2006, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1996. @@ -49,10 +49,13 @@ But not all systems have support for the /proc filesystem. If it is not available we simply return 1 since there is no way. */ +#include + + /* Other architectures use different formats for /proc/cpuinfo. This provides a hook for alternative parsers. */ #ifndef GET_NPROCS_PARSER -# define GET_NPROCS_PARSER(FP, BUFFER, RESULT) \ +# define GET_NPROCS_PARSER(FD, BUFFER, CP, RE, BUFFER_END, RESULT) \ do \ { \ (RESULT) = 0; \ @@ -60,45 +63,89 @@ "processor". We don't have to fear extremely long lines since \ the kernel will not generate them. 8192 bytes are really \ enough. */ \ - while (fgets_unlocked (BUFFER, sizeof (BUFFER), FP) != NULL) \ - if (strncmp (BUFFER, "processor", 9) == 0) \ + char *l; \ + while ((l = next_line (FD, BUFFER, &CP, &RE, BUFFER_END)) != NULL) \ + if (strncmp (l, "processor", 9) == 0) \ ++(RESULT); \ } \ while (0) #endif +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_not_cancel (fd, *re, buffer_end - *re); + if (n < 0) + return NULL; + + *re += n; + } + + res = *cp; + nl = memchr (*cp, '\n', *re - *cp); + } + + if (nl == NULL) + nl = *re - 1; + } + + *cp = nl + 1; + assert (*cp <= *re); + + return res == *re ? NULL : res; +} + + int __get_nprocs () { /* XXX Here will come a test for the new system call. */ char buffer[8192]; + char *const buffer_end = buffer + sizeof (buffer); + char *cp = buffer_end; + char *re = buffer_end; int result = 1; +#ifdef O_CLOEXEC + const int flags = O_RDONLY | O_CLOEXEC; +#else + const int flags = O_RDONLY; +#endif /* The /proc/stat format is more uniform, use it by default. */ - FILE *fp = fopen ("/proc/stat", "rc"); - if (fp != NULL) + int fd = open_not_cancel_2 ("/proc/stat", flags); + if (fd != -1) { - /* No threads use this stream. */ - __fsetlocking (fp, FSETLOCKING_BYCALLER); - result = 0; - while (fgets_unlocked (buffer, sizeof (buffer), fp) != NULL) - if (strncmp (buffer, "cpu", 3) == 0 && isdigit (buffer[3])) + + char *l; + while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) + if (strncmp (l, "cpu", 3) == 0 && isdigit (l[3])) ++result; - fclose (fp); + close_not_cancel_no_status (fd); } else { - fp = fopen ("/proc/cpuinfo", "rc"); - if (fp != NULL) + fd = open_not_cancel_2 ("/proc/cpuinfo", flags); + if (fd != -1) { - /* No threads use this stream. */ - __fsetlocking (fp, FSETLOCKING_BYCALLER); - GET_NPROCS_PARSER (fp, buffer, result); - fclose (fp); + GET_NPROCS_PARSER (fd, buffer, cp, re, buffer_end, result); + close_not_cancel_no_status (fd); } } @@ -141,7 +188,7 @@ __get_nprocs_conf () #ifdef GET_NPROCS_CONF_PARSER /* If we haven't found an appropriate entry return 1. */ - FILE *fp = fopen ("/proc/cpuinfo", "rc"); + FILE *fp = fopen ("/proc/cpuinfo", "rce"); if (fp != NULL) { char buffer[8192]; diff --git a/sysdeps/unix/sysv/linux/sparc/getsysstats.c b/sysdeps/unix/sysv/linux/sparc/getsysstats.c index f064b37..e96a8e5 100644 --- a/sysdeps/unix/sysv/linux/sparc/getsysstats.c +++ b/sysdeps/unix/sysv/linux/sparc/getsysstats.c @@ -1,5 +1,5 @@ /* Determine various system internal values, Linux/Sparc version. - Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 1999, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Schwab and Jakub Jelinek @@ -21,7 +21,7 @@ /* We need to define a special parser for /proc/cpuinfo. */ -#define GET_NPROCS_PARSER(FP, BUFFER, RESULT) \ +#define GET_NPROCS_PARSER(FD, BUFFER, CP, RE, BUFFER_END, RESULT) \ do \ { \ (RESULT) = 0; \ @@ -29,8 +29,9 @@ active cpus. We don't have to fear extremely long lines since \ the kernel will not generate them. 8192 bytes are really \ enough. */ \ - while (fgets_unlocked (BUFFER, sizeof (BUFFER), FP) != NULL) \ - if (sscanf (BUFFER, "ncpus active : %d", &(RESULT)) == 1) \ + char *l; \ + while ((l = next_line (FD, BUFFER, &CP, &RE, BUFFER_END)) != NULL) \ + if (sscanf (l, "ncpus active : %d", &(RESULT)) == 1) \ break; \ } \ while (0) -- 2.7.4