changeset 16777:30ef6011648b

New module 'getrusage'. * lib/sys_resource.in.h: Include arg-nonnull.h, c++defs.h, warn-on-use.h. (getrusage): New declaration. * lib/getrusage.c: New file. * m4/getrusage.m4: New file. * m4/sys_resource_h.m4 (gl_HEADER_SYS_RESOURCE): Test whether getrusage is declared. (gl_SYS_RESOURCE_H_DEFAULTS): Initialize GNULIB_GETRUSAGE, HAVE_GETRUSAGE. * modules/sys_resource (Depends-on): Add snippet/arg-nonnull, snippet/c++defs, snippet/warn-on-use. (Makefile.am): Update generation of sys/resource.h. Substitute GNULIB_GETRUSAGE, HAVE_GETRUSAGE. * modules/getrusage: New file. * doc/posix-functions/getrusage.texi: Mention the new module.
author Bruno Haible <bruno@clisp.org>
date Fri, 13 Apr 2012 00:48:57 +0200
parents 38f34fc9b7fe
children 86a111c85915
files ChangeLog doc/posix-functions/getrusage.texi lib/getrusage.c lib/sys_resource.in.h m4/getrusage.m4 m4/sys_resource_h.m4 modules/getrusage modules/sys_resource
diffstat 8 files changed, 248 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2012-04-12  Bruno Haible  <bruno@clisp.org>
+
+	New module 'getrusage'.
+	* lib/sys_resource.in.h: Include arg-nonnull.h, c++defs.h,
+	warn-on-use.h.
+	(getrusage): New declaration.
+	* lib/getrusage.c: New file.
+	* m4/getrusage.m4: New file.
+	* m4/sys_resource_h.m4 (gl_HEADER_SYS_RESOURCE): Test whether getrusage
+	is declared.
+	(gl_SYS_RESOURCE_H_DEFAULTS): Initialize GNULIB_GETRUSAGE,
+	HAVE_GETRUSAGE.
+	* modules/sys_resource (Depends-on): Add snippet/arg-nonnull,
+	snippet/c++defs, snippet/warn-on-use.
+	(Makefile.am): Update generation of sys/resource.h. Substitute
+	GNULIB_GETRUSAGE, HAVE_GETRUSAGE.
+	* modules/getrusage: New file.
+	* doc/posix-functions/getrusage.texi: Mention the new module.
+
 2012-04-12  Bruno Haible  <bruno@clisp.org>
 
 	Tests for module 'sys_resource'.
--- a/doc/posix-functions/getrusage.texi
+++ b/doc/posix-functions/getrusage.texi
@@ -4,18 +4,18 @@
 
 POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/getrusage.html}
 
-Gnulib module: ---
+Gnulib module: getrusage
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+This function is missing on some platforms:
+Minix 3.1.8, Solaris 2.4, mingw, MSVC 9.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
 @item
-This function is missing on some platforms:
-Minix 3.1.8, Solaris 2.4, mingw, MSVC 9.
-@item
 Many platforms don't fill in all the fields of @code{struct rusage} with
 meaningful values.
 @end itemize
new file mode 100644
--- /dev/null
+++ b/lib/getrusage.c
@@ -0,0 +1,131 @@
+/* getrusage replacement for systems which lack it.
+
+   Copyright (C) 2012 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible, 2012.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <sys/resource.h>
+
+#include <errno.h>
+#include <string.h>
+
+/* Get uint64_t.  */
+#include <stdint.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+#else
+
+# include <sys/times.h>
+# include <unistd.h>
+#endif
+
+int
+getrusage (int who, struct rusage *usage_p)
+{
+  if (who == RUSAGE_SELF || who == RUSAGE_CHILDREN)
+    {
+      /* Clear all unsupported members of 'struct rusage'.  */
+      memset (usage_p, '\0', sizeof (struct rusage));
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+      if (who == RUSAGE_SELF)
+        {
+          /* Fill in the ru_utime and ru_stime members.  */
+          FILETIME creation_time;
+          FILETIME exit_time;
+          FILETIME kernel_time;
+          FILETIME user_time;
+
+          if (GetProcessTimes (GetCurrentProcess (),
+                               &creation_time, &exit_time,
+                               &kernel_time, &user_time))
+            {
+              /* Convert to microseconds, rounding.  */
+              uint64_t kernel_usec =
+                ((((uint64_t) kernel_time.dwHighDateTime << 32)
+                  | (uint64_t) kernel_time.dwLowDateTime)
+                 + 5) / 10;
+              uint64_t user_usec =
+                ((((uint64_t) user_time.dwHighDateTime << 32)
+                  | (uint64_t) user_time.dwLowDateTime)
+                 + 5) / 10;
+
+              usage_p->ru_utime.tv_sec = user_usec / 1000000U;
+              usage_p->ru_utime.tv_usec = user_usec % 1000000U;
+              usage_p->ru_stime.tv_sec = kernel_usec / 1000000U;
+              usage_p->ru_stime.tv_usec = kernel_usec % 1000000U;
+            }
+        }
+#else
+      /* Fill in the ru_utime and ru_stime members.  */
+      {
+        struct tms time;
+
+        if (times (&time) != (clock_t) -1)
+          {
+            /* Number of clock ticks per second.  */
+            unsigned int clocks_per_second = sysconf (_SC_CLK_TCK);
+
+            if (clocks_per_second > 0)
+              {
+                clock_t user_ticks;
+                clock_t system_ticks;
+
+                uint64_t user_usec;
+                uint64_t system_usec;
+
+                if (who == RUSAGE_CHILDREN)
+                  {
+                    user_ticks   = time.tms_cutime;
+                    system_ticks = time.tms_cstime;
+                  }
+                else
+                  {
+                    user_ticks   = time.tms_utime;
+                    system_ticks = time.tms_stime;
+                  }
+
+                user_usec =
+                  (((uint64_t) user_ticks * (uint64_t) 1000000U)
+                   + clocks_per_second / 2) / clocks_per_second;
+                system_usec =
+                  (((uint64_t) system_ticks * (uint64_t) 1000000U)
+                   + clocks_per_second / 2) / clocks_per_second;
+
+                usage_p->ru_utime.tv_sec = user_usec / 1000000U;
+                usage_p->ru_utime.tv_usec = user_usec % 1000000U;
+                usage_p->ru_stime.tv_sec = system_usec / 1000000U;
+                usage_p->ru_stime.tv_usec = system_usec % 1000000U;
+              }
+          }
+      }
+#endif
+
+      return 0;
+    }
+  else
+    {
+      errno = EINVAL;
+      return -1;
+    }
+}
--- a/lib/sys_resource.in.h
+++ b/lib/sys_resource.in.h
@@ -81,5 +81,31 @@
 
 #endif
 
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
+
+/* The definition of _GL_ARG_NONNULL is copied here.  */
+
+/* The definition of _GL_WARN_ON_USE is copied here.  */
+
+
+/* Declare overridden functions.  */
+
+
+#if @GNULIB_GETRUSAGE@
+# if !@HAVE_GETRUSAGE@
+_GL_FUNCDECL_SYS (getrusage, int, (int who, struct rusage *usage_p)
+                                  _GL_ARG_NONNULL ((2)));
+# endif
+_GL_CXXALIAS_SYS (getrusage, int, (int who, struct rusage *usage_p));
+_GL_CXXALIASWARN (getrusage);
+#elif defined GNULIB_POSIXCHECK
+# undef getrusage
+# if HAVE_RAW_DECL_GETRUSAGE
+_GL_WARN_ON_USE (getrusage, "getrusage is unportable - "
+                 "use gnulib module getrusage for portability");
+# endif
+#endif
+
+
 #endif /* _@GUARD_PREFIX@_SYS_RESOURCE_H */
 #endif /* _@GUARD_PREFIX@_SYS_RESOURCE_H */
new file mode 100644
--- /dev/null
+++ b/m4/getrusage.m4
@@ -0,0 +1,14 @@
+# getrusage.m4 serial 1
+dnl Copyright (C) 2012 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_GETRUSAGE],
+[
+  AC_REQUIRE([gl_SYS_RESOURCE_H_DEFAULTS])
+  AC_CHECK_FUNCS_ONCE([getrusage])
+  if test $ac_cv_func_getrusage = no; then
+    HAVE_GETRUSAGE=0
+  fi
+])
--- a/m4/sys_resource_h.m4
+++ b/m4/sys_resource_h.m4
@@ -1,4 +1,4 @@
-# sys_resource_h.m4 serial 1
+# sys_resource_h.m4 serial 2
 dnl Copyright (C) 2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -15,6 +15,19 @@
     HAVE_SYS_RESOURCE_H=0
   fi
   AC_SUBST([HAVE_SYS_RESOURCE_H])
+
+  dnl Check for declarations of anything we want to poison if the
+  dnl corresponding gnulib module is not in use.
+  gl_WARN_ON_USE_PREPARE([[
+#if HAVE_SYS_RESOURCE_H
+/* At least FreeBSD 5.0 needs extra headers before <sys/resource.h>
+   will compile.  */
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/resource.h>
+#endif
+    ]],
+    [getrusage])
 ])
 
 AC_DEFUN([gl_SYS_RESOURCE_MODULE_INDICATOR],
@@ -28,4 +41,7 @@
 
 AC_DEFUN([gl_SYS_RESOURCE_H_DEFAULTS],
 [
+  GNULIB_GETRUSAGE=0;     AC_SUBST([GNULIB_GETRUSAGE])
+  dnl Assume proper GNU behavior unless another module says otherwise.
+  HAVE_GETRUSAGE=1;       AC_SUBST([HAVE_GETRUSAGE])
 ])
new file mode 100644
--- /dev/null
+++ b/modules/getrusage
@@ -0,0 +1,28 @@
+Description:
+getrusage() function: Get resource usage of current process.
+
+Files:
+lib/getrusage.c
+m4/getrusage.m4
+
+Depends-on:
+sys_resource
+stdint          [test $HAVE_GETRUSAGE = 0]
+
+configure.ac:
+gl_FUNC_GETRUSAGE
+if test $HAVE_GETRUSAGE = 0; then
+  AC_LIBOBJ([getrusage])
+fi
+gl_SYS_RESOURCE_MODULE_INDICATOR([getrusage])
+
+Makefile.am:
+
+Include:
+<sys/resource.h>
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible
--- a/modules/sys_resource
+++ b/modules/sys_resource
@@ -7,6 +7,9 @@
 
 Depends-on:
 include_next
+snippet/arg-nonnull
+snippet/c++defs
+snippet/warn-on-use
 sys_time
 
 configure.ac:
@@ -18,7 +21,7 @@
 
 # We need the following in order to create <sys/resource.h> when the system
 # doesn't have one.
-sys/resource.h: sys_resource.in.h $(top_builddir)/config.status
+sys/resource.h: sys_resource.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
 	$(AM_V_at)$(MKDIR_P) sys
 	$(AM_V_GEN)rm -f $@-t $@ && \
 	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
@@ -28,6 +31,11 @@
 	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
 	      -e 's|@''NEXT_SYS_RESOURCE_H''@|$(NEXT_SYS_RESOURCE_H)|g' \
 	      -e 's|@''HAVE_SYS_RESOURCE_H''@|$(HAVE_SYS_RESOURCE_H)|g' \
+	      -e 's/@''GNULIB_GETRUSAGE''@/$(GNULIB_GETRUSAGE)/g' \
+	      -e 's/@''HAVE_GETRUSAGE''@/$(HAVE_GETRUSAGE)/g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
 	      < $(srcdir)/sys_resource.in.h; \
 	} > $@-t && \
 	mv -f $@-t $@