Skip to content

Commit

Permalink
* sysdeps/unix/sysv/linux/getsysstats.c (next_line): New function.
Browse files Browse the repository at this point in the history
	(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.
  • Loading branch information
Ulrich Drepper committed Feb 15, 2009
1 parent 4c869eb commit f43b4be
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 23 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
2009-02-15 Ulrich Drepper <drepper@redhat.com>

* 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 <drepper@redhat.com>

[BZ #5381]
Expand Down
85 changes: 66 additions & 19 deletions sysdeps/unix/sysv/linux/getsysstats.c
Original file line number Diff line number Diff line change
@@ -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 <drepper@cygnus.com>, 1996.
Expand Down Expand Up @@ -49,56 +49,103 @@
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 <not-cancel.h>


/* 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; \
/* Read all lines and count the lines starting with the string \
"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);
}
}

Expand Down Expand Up @@ -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];
Expand Down
9 changes: 5 additions & 4 deletions sysdeps/unix/sysv/linux/sparc/getsysstats.c
Original file line number Diff line number Diff line change
@@ -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 <schwab@suse.de> and
Jakub Jelinek <jj@ultra.linux.cz>
Expand All @@ -21,16 +21,17 @@


/* 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; \
/* Find the line that contains the information about the number of \
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)
Expand Down

0 comments on commit f43b4be

Please sign in to comment.