diff options
Diffstat (limited to 'gnulib-tests/getrusage.c')
-rw-r--r-- | gnulib-tests/getrusage.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/gnulib-tests/getrusage.c b/gnulib-tests/getrusage.c new file mode 100644 index 0000000..5d302d5 --- /dev/null +++ b/gnulib-tests/getrusage.c @@ -0,0 +1,131 @@ +/* getrusage replacement for systems which lack it. + + Copyright (C) 2012-2020 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 <https://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 __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 __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; + } +} |