1 #ifndef STRACE_TESTS_TIME_ENJOYMENT_H
2 # define STRACE_TESTS_TIME_ENJOYMENT_H
3
4 # include <fcntl.h>
5 # include <sched.h>
6 # include <time.h>
7 # include <sys/types.h>
8 # include <sys/stat.h>
9
10 enum {
11 NUM_USER_ITERS_SQRT = 2000,
12 NUM_USER_ITERS = NUM_USER_ITERS_SQRT * NUM_USER_ITERS_SQRT,
13 READ_BUF_SIZE = 65536,
14 READ_ITER = 128,
15 };
16
17 static inline uint64_t
18 nsecs(struct timespec *ts)
19 {
20 return (uint64_t) ts->tv_sec * 1000000000 + ts->tv_nsec;
21 }
22
23 static inline void
24 enjoy_time(uint64_t cputime_limit)
25 {
26 struct timespec ts = { 0 };
27 volatile int dummy = 0;
28
29 /* Enjoying my user time */
30 for (size_t i = 0; i < NUM_USER_ITERS_SQRT; ++i) {
31 if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
32 if (nsecs(&ts) >= cputime_limit)
33 break;
34 }
35
36 for (size_t j = 0; j < NUM_USER_ITERS; ++j)
37 ++dummy;
38 }
39
40 /* Enjoying my system time */
41 ssize_t ret;
42 int fd;
43 char buf[READ_BUF_SIZE];
44
45 while (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0) {
46 for (size_t i = 0; i < READ_ITER; i++) {
47 /* We are fine even if the calls fail. */
48 fd = open("/proc/self/status", O_RDONLY);
49 /*
50 * Working around "ignoring return value of 'read'
51 * declared with attribute 'warn_unused_result'".
52 */
53 ret = read(fd, buf, sizeof(buf));
54 close(fd);
55 if (ret)
56 continue;
57 }
58
59 if (nsecs(&ts) >= cputime_limit * 3)
60 break;
61
62 sched_yield();
63 }
64 }
65
66 #endif /* !STRACE_TESTS_TIME_ENJOYMENT_H */