blob: e540a69c445eefcd0d40f83e1daf547f8aeed8f9 [file] [log] [blame]
Caspar Zhanga88874b2011-12-22 19:04:31 +08001/*
2 * getrusage04 - accuracy of getrusage() with RUSAGE_THREAD
3 *
4 * This program is used for testing the following upstream commit:
5 * 761b1d26df542fd5eb348837351e4d2f3bc7bffe.
6 *
7 * getrusage() returns cpu resource usage with accuracy of 10ms
8 * when RUSAGE_THREAD is specified to the argument who. Meanwhile,
9 * accuracy is 1ms when RUSAGE_SELF is specified. This bad accuracy
10 * of getrusage() caused a big impact on some application which is
11 * critical to accuracy of cpu usage. The upstream fix removed
12 * casts to clock_t in task_u/stime(), to keep granularity of
13 * cputime_t over the calculation.
14 *
15 * Note that the accuracy on powerpc and s390x systems is always
16 * 10ms when either RUSAGE_THREAD or RUSAGE_SELF specified, so
17 * this test won't be executed on those platforms.
18 *
19 * Copyright (C) 2011 Red Hat, Inc.
Cyril Hrubis07f4e542013-02-21 17:23:57 +010020 * Copyright (C) 2013 Cyril Hrubis <chrubis@suse.cz>
21 *
Caspar Zhanga88874b2011-12-22 19:04:31 +080022 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of version 2 of the GNU General Public
24 * License as published by the Free Software Foundation.
25 *
26 * This program is distributed in the hope that it would be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Further, this software is distributed without any warranty that it
31 * is free of the rightful claim of any third person regarding
32 * infringement or the like. Any license provided herein, whether
33 * implied or otherwise, applies only to this software file. Patent
34 * licenses, if any, provided herein do not apply to combinations of
35 * this program with other software, or any other product whatsoever.
36 *
37 * You should have received a copy of the GNU General Public License
38 * along with this program; if not, write the Free Software
39 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
40 * 02110-1301, USA.
41 */
Cyril Hrubis07f4e542013-02-21 17:23:57 +010042
Caspar Zhanga88874b2011-12-22 19:04:31 +080043#define _GNU_SOURCE
44#include <sys/types.h>
45#include <sys/resource.h>
46#include <sys/time.h>
47#include <errno.h>
48#include <stdio.h>
49#include <stdlib.h>
Cyril Hrubis07f4e542013-02-21 17:23:57 +010050#include <time.h>
Caspar Zhanga88874b2011-12-22 19:04:31 +080051
52#include "test.h"
Caspar Zhanga88874b2011-12-22 19:04:31 +080053#include "safe_macros.h"
Cyril Hrubis0647a002013-11-21 11:05:53 +010054#include "lapi/posix_clocks.h"
Caspar Zhanga88874b2011-12-22 19:04:31 +080055
56char *TCID = "getrusage04";
57int TST_TOTAL = 1;
58
Caspar Zhanga88874b2011-12-22 19:04:31 +080059#define RECORD_MAX 20
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +010060#define FACTOR_MAX 10
Caspar Zhanga88874b2011-12-22 19:04:31 +080061
62#ifndef RUSAGE_THREAD
63#define RUSAGE_THREAD 1
64#endif
65
Cyril Hrubis07f4e542013-02-21 17:23:57 +010066static long BIAS_MAX;
67
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +010068static int opt_factor;
69static char *factor_str;
70static long factor_nr = 1;
71
72option_t child_options[] = {
Wanlong Gao354ebb42012-12-07 10:10:04 +080073 {"m:", &opt_factor, &factor_str},
74 {NULL, NULL, NULL}
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +010075};
76
77static void fusage(void);
Caspar Zhanga88874b2011-12-22 19:04:31 +080078static void busyloop(long wait);
79static void setup(void);
80static void cleanup(void);
81
82int main(int argc, char *argv[])
83{
84 struct rusage usage;
85 unsigned long ulast, udelta, slast, sdelta;
86 int i, lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020087 const char *msg;
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +010088 char msg_string[BUFSIZ];
Caspar Zhanga88874b2011-12-22 19:04:31 +080089
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +010090 msg = parse_opts(argc, argv, child_options, fusage);
Caspar Zhanga88874b2011-12-22 19:04:31 +080091 if (msg != NULL)
92 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
93
94#if (__powerpc__) || (__powerpc64__) || (__s390__) || (__s390x__)
95 tst_brkm(TCONF, NULL, "This test is not designed for current system");
96#endif
97
98 setup();
99
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +0100100 if (opt_factor)
101 factor_nr = SAFE_STRTOL(cleanup, factor_str, 0, FACTOR_MAX);
102
103 tst_resm(TINFO, "Using %ld as multiply factor for max [us]time "
104 "increment (1000+%ldus)!", factor_nr, BIAS_MAX * factor_nr);
105
Caspar Zhanga88874b2011-12-22 19:04:31 +0800106 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800107 tst_count = 0;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800108 i = 0;
Caspar Zhanga88874b2011-12-22 19:04:31 +0800109 SAFE_GETRUSAGE(cleanup, RUSAGE_THREAD, &usage);
110 tst_resm(TINFO, "utime:%12luus; stime:%12luus",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800111 usage.ru_utime.tv_usec, usage.ru_stime.tv_usec);
Jan Stancek46c552e2012-03-07 16:51:52 +0100112 ulast = usage.ru_utime.tv_usec;
113 slast = usage.ru_stime.tv_usec;
114
Caspar Zhanga88874b2011-12-22 19:04:31 +0800115 while (i < RECORD_MAX) {
116 SAFE_GETRUSAGE(cleanup, RUSAGE_THREAD, &usage);
117 udelta = usage.ru_utime.tv_usec - ulast;
118 sdelta = usage.ru_stime.tv_usec - slast;
119 if (udelta > 0 || sdelta > 0) {
120 i++;
121 tst_resm(TINFO, "utime:%12luus; stime:%12luus",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800122 usage.ru_utime.tv_usec,
123 usage.ru_stime.tv_usec);
124 if (udelta > 1000 + (BIAS_MAX * factor_nr)) {
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +0100125 sprintf(msg_string,
126 "utime increased > %ldus:",
127 1000 + BIAS_MAX * factor_nr);
128 tst_brkm(TFAIL, cleanup, msg_string,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800129 " delta = %luus", udelta);
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +0100130 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800131 if (sdelta > 1000 + (BIAS_MAX * factor_nr)) {
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +0100132 sprintf(msg_string,
133 "stime increased > %ldus:",
134 1000 + BIAS_MAX * factor_nr);
135 tst_brkm(TFAIL, cleanup, msg_string,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800136 " delta = %luus", sdelta);
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +0100137 }
Caspar Zhanga88874b2011-12-22 19:04:31 +0800138 }
139 ulast = usage.ru_utime.tv_usec;
140 slast = usage.ru_stime.tv_usec;
141 busyloop(100000);
142 }
143 }
Cyril Hrubis07f4e542013-02-21 17:23:57 +0100144
145 tst_resm(TPASS, "Test Passed");
146
Caspar Zhanga88874b2011-12-22 19:04:31 +0800147 cleanup();
148 tst_exit();
149}
150
Filippo ARCIDIACONOfd875252012-02-23 11:57:58 +0100151static void fusage(void)
152{
153 printf(" -m n use n as multiply factor for max [us]time "
154 "increment (1000+(1000*n)us),\n default value is 1\n");
155}
156
Caspar Zhanga88874b2011-12-22 19:04:31 +0800157static void busyloop(long wait)
158{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800159 while (wait--) ;
Caspar Zhanga88874b2011-12-22 19:04:31 +0800160}
161
Cyril Hrubis07f4e542013-02-21 17:23:57 +0100162/*
163 * The resolution of getrusage timers currently depends on CONFIG_HZ settings,
164 * as they are measured in jiffies.
165 *
166 * The problem is that there is no reasonable API to get either getrusage
167 * timers resolution or duration of jiffie.
168 *
169 * Here we use clock_getres() with linux specific CLOCK_REALTIME_COARSE (added
170 * in 2.6.32) which is also based on jiffies. This timer has the same
171 * granularity as getrusage but it's not guaranteed and it may change in the
172 * future.
173 *
174 * The default value for resolution was choosen to be 4ms as it corresponds to
175 * CONFIG_HZ=250 which seems to be default value.
176 */
Cyril Hrubis07f4e542013-02-21 17:23:57 +0100177static unsigned long guess_timer_resolution(void)
178{
179 struct timespec res;
180
181 if (clock_getres(CLOCK_REALTIME_COARSE, &res)) {
182 tst_resm(TINFO,
183 "CLOCK_REALTIME_COARSE not supported, using 4000 us");
184 return 4000;
185 }
186
187 if (res.tv_nsec < 1000000 || res.tv_nsec > 10000000) {
188 tst_resm(TINFO, "Unexpected CLOCK_REALTIME_COARSE resolution,"
189 " using 4000 us");
190 return 4000;
191 }
192
193 tst_resm(TINFO, "Expected timers granularity is %li us",
194 res.tv_nsec / 1000);
195
196 return res.tv_nsec / 1000;
197}
198
Caspar Zhanga88874b2011-12-22 19:04:31 +0800199static void setup(void)
200{
201 tst_sig(NOFORK, DEF_HANDLER, cleanup);
202
Jan Stancekc26dd372013-10-17 12:48:46 +0200203 if (tst_is_virt(VIRT_XEN))
204 tst_brkm(TCONF, NULL, "This testcase is not supported on Xen.");
205
Cyril Hrubis07f4e542013-02-21 17:23:57 +0100206 BIAS_MAX = guess_timer_resolution();
207
Caspar Zhanga88874b2011-12-22 19:04:31 +0800208 TEST_PAUSE;
209}
210
211static void cleanup(void)
212{
Caspar Zhanga88874b2011-12-22 19:04:31 +0800213}