blob: c34a9a3201cb2a85658456d69c81d0588ff5a4d1 [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 */
Dmitry V. Levinb6b38fa2015-12-15 15:26:29 +000072#undef USE_LIBC_SYSCALL
73#if defined __NR_times && \
74 !defined(LINUX_MIPSN32) && \
75 !(defined __x86_64__ && defined __ILP32__)
76# define USE_LIBC_SYSCALL 1
77#endif
78
79#if defined USE_LIBC_SYSCALL
80 long res = syscall(__NR_times, &tbuf);
81
82 if (-1L == res)
83 return 77;
84 else
85 llres = (unsigned long) res;
86#elif defined __NR_times && defined __x86_64__ && defined __ILP32__
87 register long arg asm("rdi") = (long) &tbuf;
88 asm volatile("syscall\n\t"
89 : "=a"(llres)
90 : "0"(__NR_times), "r"(arg)
91 : "memory", "cc", "r11", "cx");
92 if (llres > 0xfffffffffffff000)
93 return 77;
94#else
Dmitry V. Levinfc0a22d2015-12-06 04:51:57 +000095 clock_t res = times(&tbuf);
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030096
Dmitry V. Levin4bbed302015-12-06 05:28:11 +000097 if ((clock_t) -1 == res)
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +030098 return 77;
Dmitry V. Levin4bbed302015-12-06 05:28:11 +000099 if (sizeof(res) < sizeof(unsigned long long))
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +0300100 llres = (unsigned long) res;
101 else
102 llres = res;
Dmitry V. Levin4bbed302015-12-06 05:28:11 +0000103#endif
Eugene Syromyatnikov7a036052015-08-04 15:52:55 +0300104
105 printf("times({tms_utime=%llu, tms_stime=%llu, ",
106 (unsigned long long) tbuf.tms_utime,
107 (unsigned long long) tbuf.tms_stime);
108 printf("tms_cutime=%llu, tms_cstime=%llu}) = %llu\n",
109 (unsigned long long) tbuf.tms_cutime,
110 (unsigned long long) tbuf.tms_cstime,
111 llres);
112 puts("+++ exited with 0 +++");
113
114 return 0;
115}