maint: update copyright
[gnulib.git] / lib / getrusage.c
1 /* getrusage replacement for systems which lack it.
2
3    Copyright (C) 2012-2014 Free Software Foundation, Inc.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 /* Written by Bruno Haible, 2012.  */
19
20 #include <config.h>
21
22 /* Specification.  */
23 #include <sys/resource.h>
24
25 #include <errno.h>
26 #include <string.h>
27
28 /* Get uint64_t.  */
29 #include <stdint.h>
30
31 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
32
33 # define WIN32_LEAN_AND_MEAN
34 # include <windows.h>
35
36 #else
37
38 # include <sys/times.h>
39 # include <unistd.h>
40 #endif
41
42 int
43 getrusage (int who, struct rusage *usage_p)
44 {
45   if (who == RUSAGE_SELF || who == RUSAGE_CHILDREN)
46     {
47       /* Clear all unsupported members of 'struct rusage'.  */
48       memset (usage_p, '\0', sizeof (struct rusage));
49
50 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
51       if (who == RUSAGE_SELF)
52         {
53           /* Fill in the ru_utime and ru_stime members.  */
54           FILETIME creation_time;
55           FILETIME exit_time;
56           FILETIME kernel_time;
57           FILETIME user_time;
58
59           if (GetProcessTimes (GetCurrentProcess (),
60                                &creation_time, &exit_time,
61                                &kernel_time, &user_time))
62             {
63               /* Convert to microseconds, rounding.  */
64               uint64_t kernel_usec =
65                 ((((uint64_t) kernel_time.dwHighDateTime << 32)
66                   | (uint64_t) kernel_time.dwLowDateTime)
67                  + 5) / 10;
68               uint64_t user_usec =
69                 ((((uint64_t) user_time.dwHighDateTime << 32)
70                   | (uint64_t) user_time.dwLowDateTime)
71                  + 5) / 10;
72
73               usage_p->ru_utime.tv_sec = user_usec / 1000000U;
74               usage_p->ru_utime.tv_usec = user_usec % 1000000U;
75               usage_p->ru_stime.tv_sec = kernel_usec / 1000000U;
76               usage_p->ru_stime.tv_usec = kernel_usec % 1000000U;
77             }
78         }
79 #else
80       /* Fill in the ru_utime and ru_stime members.  */
81       {
82         struct tms time;
83
84         if (times (&time) != (clock_t) -1)
85           {
86             /* Number of clock ticks per second.  */
87             unsigned int clocks_per_second = sysconf (_SC_CLK_TCK);
88
89             if (clocks_per_second > 0)
90               {
91                 clock_t user_ticks;
92                 clock_t system_ticks;
93
94                 uint64_t user_usec;
95                 uint64_t system_usec;
96
97                 if (who == RUSAGE_CHILDREN)
98                   {
99                     user_ticks   = time.tms_cutime;
100                     system_ticks = time.tms_cstime;
101                   }
102                 else
103                   {
104                     user_ticks   = time.tms_utime;
105                     system_ticks = time.tms_stime;
106                   }
107
108                 user_usec =
109                   (((uint64_t) user_ticks * (uint64_t) 1000000U)
110                    + clocks_per_second / 2) / clocks_per_second;
111                 system_usec =
112                   (((uint64_t) system_ticks * (uint64_t) 1000000U)
113                    + clocks_per_second / 2) / clocks_per_second;
114
115                 usage_p->ru_utime.tv_sec = user_usec / 1000000U;
116                 usage_p->ru_utime.tv_usec = user_usec % 1000000U;
117                 usage_p->ru_stime.tv_sec = system_usec / 1000000U;
118                 usage_p->ru_stime.tv_usec = system_usec % 1000000U;
119               }
120           }
121       }
122 #endif
123
124       return 0;
125     }
126   else
127     {
128       errno = EINVAL;
129       return -1;
130     }
131 }