blob: 17a8369888cde0aa3ad7987e9cc9bfd07986fb02 [file] [log] [blame]
Pierre Ossman236c03c2014-07-04 14:12:49 +02001/* Copyright 2013-2014 Pierre Ossman <ossman@cendio.se> for Cendio AB
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19#include <stdint.h>
Pierre Ossman8ac31112015-02-06 13:50:36 +010020#include <stdlib.h>
21#include <string.h>
Pierre Ossman236c03c2014-07-04 14:12:49 +020022
23#ifdef WIN32
24#include <windows.h>
25#else
26#include <sys/resource.h>
Pierre Ossman38a1c702016-12-20 12:32:37 +010027#include <sys/time.h>
Pierre Ossman236c03c2014-07-04 14:12:49 +020028#endif
29
Pierre Ossman8ac31112015-02-06 13:50:36 +010030#include "util.h"
31
Pierre Ossman236c03c2014-07-04 14:12:49 +020032#ifdef WIN32
Pierre Ossmanb591c9d2015-11-09 15:29:30 +010033typedef struct {
34 FILETIME kernelTime;
35 FILETIME userTime;
36} syscounter_t;
Pierre Ossman236c03c2014-07-04 14:12:49 +020037#else
Pierre Ossman8ac31112015-02-06 13:50:36 +010038typedef struct rusage syscounter_t;
Pierre Ossman236c03c2014-07-04 14:12:49 +020039#endif
40
Pierre Ossman8ac31112015-02-06 13:50:36 +010041static syscounter_t _globalCounter[2];
42static cpucounter_t globalCounter = _globalCounter;
43
44void startCpuCounter(void)
45{
46 startCpuCounter(globalCounter);
47}
48
49void endCpuCounter(void)
50{
51 endCpuCounter(globalCounter);
52}
53
54double getCpuCounter(void)
55{
56 return getCpuCounter(globalCounter);
57}
58
59cpucounter_t newCpuCounter(void)
60{
61 syscounter_t *c;
62
63 c = (syscounter_t*)malloc(sizeof(syscounter_t) * 2);
64 if (c == NULL)
65 return NULL;
66
67 memset(c, 0, sizeof(syscounter_t) * 2);
68
69 return c;
70}
71
72void freeCpuCounter(cpucounter_t c)
73{
74 free(c);
75}
76
77static void measureCpu(syscounter_t *counter)
Pierre Ossman236c03c2014-07-04 14:12:49 +020078{
79#ifdef WIN32
Pierre Ossmanb591c9d2015-11-09 15:29:30 +010080 FILETIME dummy1, dummy2;
Pierre Ossman236c03c2014-07-04 14:12:49 +020081
82 GetProcessTimes(GetCurrentProcess(), &dummy1, &dummy2,
Pierre Ossmanb591c9d2015-11-09 15:29:30 +010083 &counter->kernelTime, &counter->userTime);
Pierre Ossman236c03c2014-07-04 14:12:49 +020084#else
Pierre Ossman8ac31112015-02-06 13:50:36 +010085 getrusage(RUSAGE_SELF, counter);
Pierre Ossman236c03c2014-07-04 14:12:49 +020086#endif
87}
88
Pierre Ossman8ac31112015-02-06 13:50:36 +010089void startCpuCounter(cpucounter_t c)
Pierre Ossman236c03c2014-07-04 14:12:49 +020090{
Pierre Ossman8ac31112015-02-06 13:50:36 +010091 syscounter_t *s = (syscounter_t*)c;
92 measureCpu(&s[0]);
Pierre Ossman236c03c2014-07-04 14:12:49 +020093}
94
Pierre Ossman8ac31112015-02-06 13:50:36 +010095void endCpuCounter(cpucounter_t c)
Pierre Ossman236c03c2014-07-04 14:12:49 +020096{
Pierre Ossman8ac31112015-02-06 13:50:36 +010097 syscounter_t *s = (syscounter_t*)c;
98 measureCpu(&s[1]);
Pierre Ossman236c03c2014-07-04 14:12:49 +020099}
100
Pierre Ossman8ac31112015-02-06 13:50:36 +0100101double getCpuCounter(cpucounter_t c)
Pierre Ossman236c03c2014-07-04 14:12:49 +0200102{
Pierre Ossman8ac31112015-02-06 13:50:36 +0100103 syscounter_t *s = (syscounter_t*)c;
Pierre Ossmanb591c9d2015-11-09 15:29:30 +0100104 double sysSeconds, userSeconds;
Pierre Ossman236c03c2014-07-04 14:12:49 +0200105
106#ifdef WIN32
107 uint64_t counters[2];
108
Pierre Ossmanb591c9d2015-11-09 15:29:30 +0100109 counters[0] = (uint64_t)s[0].kernelTime.dwHighDateTime << 32 |
110 s[0].kernelTime.dwLowDateTime;
111 counters[1] = (uint64_t)s[1].kernelTime.dwHighDateTime << 32 |
112 s[1].kernelTime.dwLowDateTime;
Pierre Ossman236c03c2014-07-04 14:12:49 +0200113
Pierre Ossmanb591c9d2015-11-09 15:29:30 +0100114 sysSeconds = (double)(counters[1] - counters[0]) / 10000000.0;
115
116 counters[0] = (uint64_t)s[0].userTime.dwHighDateTime << 32 |
117 s[0].userTime.dwLowDateTime;
118 counters[1] = (uint64_t)s[1].userTime.dwHighDateTime << 32 |
119 s[1].userTime.dwLowDateTime;
120
121 userSeconds = (double)(counters[1] - counters[0]) / 10000000.0;
Pierre Ossman236c03c2014-07-04 14:12:49 +0200122#else
Pierre Ossmanb591c9d2015-11-09 15:29:30 +0100123 sysSeconds = (double)(s[1].ru_stime.tv_sec -
124 s[0].ru_stime.tv_sec);
125 sysSeconds += (double)(s[1].ru_stime.tv_usec -
126 s[0].ru_stime.tv_usec) / 1000000.0;
127
128 userSeconds = (double)(s[1].ru_utime.tv_sec -
129 s[0].ru_utime.tv_sec);
130 userSeconds += (double)(s[1].ru_utime.tv_usec -
131 s[0].ru_utime.tv_usec) / 1000000.0;
Pierre Ossman236c03c2014-07-04 14:12:49 +0200132#endif
133
Pierre Ossmanb591c9d2015-11-09 15:29:30 +0100134 return sysSeconds + userSeconds;
Pierre Ossman236c03c2014-07-04 14:12:49 +0200135}
Pierre Ossman38a1c702016-12-20 12:32:37 +0100136
137#ifdef WIN32
138static LARGE_INTEGER timeStart, timeEnd;
139#else
140static struct timeval timeStart, timeEnd;
141#endif
142
143void startTimeCounter(void)
144{
145#ifdef WIN32
146 QueryPerformanceCounter(&timeStart);
147#else
148 gettimeofday(&timeStart, NULL);
149#endif
150}
151
152void endTimeCounter(void)
153{
154#ifdef WIN32
155 QueryPerformanceCounter(&timeEnd);
156#else
157 gettimeofday(&timeEnd, NULL);
158#endif
159}
160
161double getTimeCounter(void)
162{
163 double time;
164
165#ifdef WIN32
166 LARGE_INTEGER freq;
167
168 QueryPerformanceFrequency(&freq);
169
170 time = timeEnd.QuadPart - timeStart.QuadPart;
171 time = time / freq.QuadPart;
172#else
173 time = (double)timeEnd.tv_sec - timeStart.tv_sec;
174 time += (double)(timeEnd.tv_usec - timeStart.tv_usec) / 1000000.0;
175#endif
176
177 return time;
178}