Merge glibc-ports into ports/ directory.
[platform/upstream/glibc.git] / rt / tst-cputimer3.c
1 /* Tests for POSIX timer implementation using another process's CPU clock.  */
2
3 #include <unistd.h>
4
5 #if _POSIX_THREADS && defined _POSIX_CPUTIME
6
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <fcntl.h>
12 #include <time.h>
13 #include <signal.h>
14 #include <sys/wait.h>
15
16 static clockid_t child_clock;
17
18 #define TEST_CLOCK child_clock
19 #define TEST_CLOCK_MISSING(clock) \
20   (setup_test () ? "other-process CPU clock timer support" : NULL)
21
22 /* This function is intended to rack up both user and system time.  */
23 static void
24 chew_cpu (void)
25 {
26   while (1)
27     {
28       static volatile char buf[4096];
29       for (int i = 0; i < 100; ++i)
30         for (size_t j = 0; j < sizeof buf; ++j)
31           buf[j] = 0xaa;
32       int nullfd = open ("/dev/null", O_WRONLY);
33       for (int i = 0; i < 100; ++i)
34         for (size_t j = 0; j < sizeof buf; ++j)
35           buf[j] = 0xbb;
36       write (nullfd, (char *) buf, sizeof buf);
37       close (nullfd);
38       if (getppid () == 1)
39         _exit (2);
40     }
41 }
42
43 static pid_t child;
44 static void
45 cleanup_child (void)
46 {
47   if (child <= 0)
48     return;
49   if (kill (child, SIGKILL) < 0 && errno != ESRCH)
50     printf ("cannot kill child %d: %m\n", child);
51   else
52     {
53       int status;
54       errno = 0;
55       if (waitpid (child, &status, 0) != child)
56         printf ("waitpid %d: %m\n", child);
57     }
58 }
59 #define CLEANUP_HANDLER cleanup_child ()
60
61 static int
62 setup_test (void)
63 {
64   /* Test timers on a process CPU clock by having a child process eating
65      CPU.  First make sure we can make such timers at all.  */
66
67   int pipefd[2];
68   if (pipe (pipefd) < 0)
69     {
70       printf ("pipe: %m\n");
71       exit (1);
72     }
73
74   child = fork ();
75
76   if (child == 0)
77     {
78       char c;
79       close (pipefd[1]);
80       if (read (pipefd[0], &c, 1) == 1)
81         chew_cpu ();
82       _exit (1);
83     }
84
85   if (child < 0)
86     {
87       printf ("fork: %m\n");
88       exit (1);
89     }
90
91   atexit (&cleanup_child);
92
93   close (pipefd[0]);
94
95   int e = clock_getcpuclockid (child, &child_clock);
96   if (e == EPERM)
97     {
98       puts ("clock_getcpuclockid does not support other processes");
99       return 1;
100     }
101   if (e != 0)
102     {
103       printf ("clock_getcpuclockid: %s\n", strerror (e));
104       exit (1);
105     }
106
107   timer_t t;
108   if (timer_create (TEST_CLOCK, NULL, &t) != 0)
109     {
110       printf ("timer_create: %m\n");
111       return 1;
112     }
113   timer_delete (t);
114
115   /* Get the child started chewing.  */
116   if (write (pipefd[1], "x", 1) != 1)
117     {
118       printf ("write to pipe: %m\n");
119       return 1;
120     }
121   close (pipefd[1]);
122
123   return 0;
124 }
125
126 #else
127 # define TEST_CLOCK_MISSING(clock) "process clocks"
128 #endif
129
130 #include "tst-timer4.c"