blob: f0e7086b2919e0629da5fe00cf3a9e976d28b1d9 [file] [log] [blame]
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +03001/**
2 * @file
3 * This test burns some CPU cycles in user space and kernel space in order to
4 * get some non-zero values returned by times(2).
5 */
6
7#ifdef HAVE_CONFIG_H
8# include "config.h"
9#endif
10
11#include <sched.h>
12#include <stdio.h>
13#include <time.h>
14#include <unistd.h>
15
Dmitry V. Levin4bbed302015-12-06 05:28:11 +000016#include <sys/syscall.h>
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030017#include <sys/times.h>
18#include <sys/wait.h>
19
20enum {
21 NUM_USER_ITERS = 1000000,
Dmitry V. Levinfc0a22d2015-12-06 04:51:57 +000022 PARENT_CPUTIME_LIMIT_NSEC = 200000000,
23 CHILD_CPUTIME_LIMIT_NSEC = 300000000
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030024};
25
26int
27main (void)
28{
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030029 struct timespec ts;
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030030 volatile int dummy;
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030031 int i;
32
Dmitry V. Levinfc0a22d2015-12-06 04:51:57 +000033 pid_t pid = fork();
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030034
35 if (pid < 0)
36 return 77;
37
Dmitry V. Levinfc0a22d2015-12-06 04:51:57 +000038 const long cputime_limit =
39 pid ? PARENT_CPUTIME_LIMIT_NSEC : CHILD_CPUTIME_LIMIT_NSEC;
40
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030041 /* Enjoying my user time */
42 while (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
Dmitry V. Levinfc0a22d2015-12-06 04:51:57 +000043 if (ts.tv_sec || ts.tv_nsec >= cputime_limit)
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030044 break;
45
Dmitry V. Levinfc0a22d2015-12-06 04:51:57 +000046 for (i = 0; i < NUM_USER_ITERS; ++i)
47 ++dummy;
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030048 }
49
50 /* Enjoying my system time */
51 while (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
Dmitry V. Levinfc0a22d2015-12-06 04:51:57 +000052 if (ts.tv_sec || ts.tv_nsec >= cputime_limit * 2)
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030053 break;
54
55 sched_yield();
56 }
57
58 if (pid == 0) {
59 return 0;
60 } else {
61 wait(NULL);
62 }
63
Dmitry V. Levinfc0a22d2015-12-06 04:51:57 +000064 struct tms tbuf;
Dmitry V. Levin4bbed302015-12-06 05:28:11 +000065 unsigned long long llres;
66
67 /*
68 * On systems where user's and kernel's long types are the same,
69 * prefer direct times syscall over libc's times function because
70 * the latter is more prone to return value truncation.
71 */
72#if !defined __NR_times \
73 || defined LINUX_MIPSN32 \
74 || defined __x86_64__ && defined __ILP32__
Dmitry V. Levinfc0a22d2015-12-06 04:51:57 +000075 clock_t res = times(&tbuf);
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030076
Dmitry V. Levin4bbed302015-12-06 05:28:11 +000077 if ((clock_t) -1 == res)
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030078 return 77;
Dmitry V. Levin4bbed302015-12-06 05:28:11 +000079 if (sizeof(res) < sizeof(unsigned long long))
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030080 llres = (unsigned long) res;
81 else
82 llres = res;
Dmitry V. Levin4bbed302015-12-06 05:28:11 +000083#else
84 long res = syscall(__NR_times, &tbuf);
85
86 if (-1L == res)
87 return 77;
88 else
89 llres = (unsigned long) res;
90#endif
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030091
92 printf("times({tms_utime=%llu, tms_stime=%llu, ",
93 (unsigned long long) tbuf.tms_utime,
94 (unsigned long long) tbuf.tms_stime);
95 printf("tms_cutime=%llu, tms_cstime=%llu}) = %llu\n",
96 (unsigned long long) tbuf.tms_cutime,
97 (unsigned long long) tbuf.tms_cstime,
98 llres);
99 puts("+++ exited with 0 +++");
100
101 return 0;
102}