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