Back to index

glibc  2.9
tst-cputimer3.c
Go to the documentation of this file.
00001 /* Tests for POSIX timer implementation using another process's CPU clock.  */
00002 
00003 #include <unistd.h>
00004 
00005 #if _POSIX_THREADS && defined _POSIX_CPUTIME
00006 
00007 #include <errno.h>
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <fcntl.h>
00012 #include <time.h>
00013 #include <signal.h>
00014 #include <sys/wait.h>
00015 
00016 static clockid_t child_clock;
00017 
00018 #define TEST_CLOCK child_clock
00019 #define TEST_CLOCK_MISSING(clock) \
00020   (setup_test () ? "other-process CPU clock timer support" : NULL)
00021 
00022 /* This function is intended to rack up both user and system time.  */
00023 static void
00024 chew_cpu (void)
00025 {
00026   while (1)
00027     {
00028       static volatile char buf[4096];
00029       for (int i = 0; i < 100; ++i)
00030        for (size_t j = 0; j < sizeof buf; ++j)
00031          buf[j] = 0xaa;
00032       int nullfd = open ("/dev/null", O_WRONLY);
00033       for (int i = 0; i < 100; ++i)
00034        for (size_t j = 0; j < sizeof buf; ++j)
00035          buf[j] = 0xbb;
00036       write (nullfd, (char *) buf, sizeof buf);
00037       close (nullfd);
00038       if (getppid () == 1)
00039        _exit (2);
00040     }
00041 }
00042 
00043 static pid_t child;
00044 static void
00045 cleanup_child (void)
00046 {
00047   if (child <= 0)
00048     return;
00049   if (kill (child, SIGKILL) < 0 && errno != ESRCH)
00050     printf ("cannot kill child %d: %m\n", child);
00051   else
00052     {
00053       int status;
00054       errno = 0;
00055       if (waitpid (child, &status, 0) != child)
00056        printf ("waitpid %d: %m\n", child);
00057     }
00058 }
00059 #define CLEANUP_HANDLER cleanup_child ()
00060 
00061 static int
00062 setup_test (void)
00063 {
00064   /* Test timers on a process CPU clock by having a child process eating
00065      CPU.  First make sure we can make such timers at all.  */
00066 
00067   int pipefd[2];
00068   if (pipe (pipefd) < 0)
00069     {
00070       printf ("pipe: %m\n");
00071       exit (1);
00072     }
00073 
00074   child = fork ();
00075 
00076   if (child == 0)
00077     {
00078       char c;
00079       close (pipefd[1]);
00080       if (read (pipefd[0], &c, 1) == 1)
00081        chew_cpu ();
00082       _exit (1);
00083     }
00084 
00085   if (child < 0)
00086     {
00087       printf ("fork: %m\n");
00088       exit (1);
00089     }
00090 
00091   atexit (&cleanup_child);
00092 
00093   close (pipefd[0]);
00094 
00095   int e = clock_getcpuclockid (child, &child_clock);
00096   if (e == EPERM)
00097     {
00098       puts ("clock_getcpuclockid does not support other processes");
00099       return 1;
00100     }
00101   if (e != 0)
00102     {
00103       printf ("clock_getcpuclockid: %s\n", strerror (e));
00104       exit (1);
00105     }
00106 
00107   timer_t t;
00108   if (timer_create (TEST_CLOCK, NULL, &t) != 0)
00109     {
00110       printf ("timer_create: %m\n");
00111       return 1;
00112     }
00113   timer_delete (t);
00114 
00115   /* Get the child started chewing.  */
00116   if (write (pipefd[1], "x", 1) != 1)
00117     {
00118       printf ("write to pipe: %m\n");
00119       return 1;
00120     }
00121   close (pipefd[1]);
00122 
00123   return 0;
00124 }
00125 
00126 #else
00127 # define TEST_CLOCK_MISSING(clock) "process clocks"
00128 #endif
00129 
00130 #include "tst-timer4.c"