1 /*-------------------------------------------------------------------------
2  *
3  * getrusage.c
4  *	  get information about resource utilisation
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *	  src/port/getrusage.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "c.h"
17 
18 #include "rusagestub.h"
19 
20 /* This code works on:
21  *		solaris_i386
22  *		solaris_sparc
23  *		hpux 9.*
24  *		win32
25  * which currently is all the supported platforms that don't have a
26  * native version of getrusage().  So, if configure decides to compile
27  * this file at all, we just use this version unconditionally.
28  */
29 
30 int
getrusage(int who,struct rusage * rusage)31 getrusage(int who, struct rusage *rusage)
32 {
33 #ifdef WIN32
34 	FILETIME	starttime;
35 	FILETIME	exittime;
36 	FILETIME	kerneltime;
37 	FILETIME	usertime;
38 	ULARGE_INTEGER li;
39 
40 	if (who != RUSAGE_SELF)
41 	{
42 		/* Only RUSAGE_SELF is supported in this implementation for now */
43 		errno = EINVAL;
44 		return -1;
45 	}
46 
47 	if (rusage == (struct rusage *) NULL)
48 	{
49 		errno = EFAULT;
50 		return -1;
51 	}
52 	memset(rusage, 0, sizeof(struct rusage));
53 	if (GetProcessTimes(GetCurrentProcess(),
54 						&starttime, &exittime, &kerneltime, &usertime) == 0)
55 	{
56 		_dosmaperr(GetLastError());
57 		return -1;
58 	}
59 
60 	/* Convert FILETIMEs (0.1 us) to struct timeval */
61 	memcpy(&li, &kerneltime, sizeof(FILETIME));
62 	li.QuadPart /= 10L;			/* Convert to microseconds */
63 	rusage->ru_stime.tv_sec = li.QuadPart / 1000000L;
64 	rusage->ru_stime.tv_usec = li.QuadPart % 1000000L;
65 
66 	memcpy(&li, &usertime, sizeof(FILETIME));
67 	li.QuadPart /= 10L;			/* Convert to microseconds */
68 	rusage->ru_utime.tv_sec = li.QuadPart / 1000000L;
69 	rusage->ru_utime.tv_usec = li.QuadPart % 1000000L;
70 #else							/* all but WIN32 */
71 
72 	struct tms	tms;
73 	int			tick_rate = CLK_TCK;	/* ticks per second */
74 	clock_t		u,
75 				s;
76 
77 	if (rusage == (struct rusage *) NULL)
78 	{
79 		errno = EFAULT;
80 		return -1;
81 	}
82 	if (times(&tms) < 0)
83 	{
84 		/* errno set by times */
85 		return -1;
86 	}
87 	switch (who)
88 	{
89 		case RUSAGE_SELF:
90 			u = tms.tms_utime;
91 			s = tms.tms_stime;
92 			break;
93 		case RUSAGE_CHILDREN:
94 			u = tms.tms_cutime;
95 			s = tms.tms_cstime;
96 			break;
97 		default:
98 			errno = EINVAL;
99 			return -1;
100 	}
101 #define TICK_TO_SEC(T, RATE)	((T)/(RATE))
102 #define TICK_TO_USEC(T,RATE)	(((T)%(RATE)*1000000)/RATE)
103 	rusage->ru_utime.tv_sec = TICK_TO_SEC(u, tick_rate);
104 	rusage->ru_utime.tv_usec = TICK_TO_USEC(u, tick_rate);
105 	rusage->ru_stime.tv_sec = TICK_TO_SEC(s, tick_rate);
106 	rusage->ru_stime.tv_usec = TICK_TO_USEC(u, tick_rate);
107 #endif							/* WIN32 */
108 
109 	return 0;
110 }
111