(root)/
strace-6.5/
tests/
times.c
       1  /*
       2   * Check decoding of times syscall.
       3   *
       4   * Copyright (c) 2015-2021 Eugene Syromyatnikov <evgsyr@gmail.com>
       5   * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
       6   * Copyright (c) 2015-2023 The strace developers.
       7   * All rights reserved.
       8   *
       9   * SPDX-License-Identifier: GPL-2.0-or-later
      10   */
      11  
      12  /**
      13   * @file
      14   * This test burns some CPU cycles in user space and kernel space in order to
      15   * get some non-zero values returned by times(2).
      16   */
      17  
      18  #include "tests.h"
      19  #include <fcntl.h>
      20  #include <sched.h>
      21  #include <stdio.h>
      22  #include <time.h>
      23  #include <unistd.h>
      24  
      25  #include "scno.h"
      26  #include <sys/stat.h>
      27  #include <sys/times.h>
      28  #include <sys/types.h>
      29  #include <sys/wait.h>
      30  
      31  #include "time_enjoyment.h"
      32  
      33  enum {
      34  	PARENT_CPUTIME_LIMIT_NSEC = 300000000,
      35  	CHILD_CPUTIME_LIMIT_NSEC = 500000000,
      36  };
      37  
      38  int
      39  main(void)
      40  {
      41  	enjoy_time(PARENT_CPUTIME_LIMIT_NSEC);
      42  
      43  	pid_t pid = fork();
      44  	if (pid < 0)
      45  		perror_msg_and_fail("fork");
      46  
      47  	if (pid == 0) {
      48  		enjoy_time(CHILD_CPUTIME_LIMIT_NSEC);
      49  
      50  		return 0;
      51  	} else {
      52  		wait(NULL);
      53  	}
      54  
      55  	struct tms tbuf;
      56  	unsigned long long llres;
      57  
      58  	/*
      59  	 * On systems where user's and kernel's long types are the same,
      60  	 * prefer direct times syscall over libc's times function because
      61  	 * the latter is more prone to return value truncation.
      62  	 */
      63  
      64  #if defined __x86_64__ && defined __ILP32__
      65  	register long arg asm("rdi") = (long) &tbuf;
      66  	asm volatile("syscall\n\t"
      67  		     : "=a"(llres)
      68  		     : "0"(__NR_times), "r"(arg)
      69  		     : "memory", "cc", "r11", "cx");
      70  	if (llres > 0xfffffffffffff000)
      71  		return 77;
      72  #elif defined __s390__ || defined LINUX_MIPSN32
      73  	clock_t res = times(&tbuf);
      74  
      75  	if ((clock_t) -1 == res)
      76  		perror_msg_and_skip("times");
      77  	if (sizeof(res) < sizeof(unsigned long long))
      78  		llres = (unsigned long) res;
      79  	else
      80  		llres = res;
      81  #else
      82  	long res = syscall(__NR_times, &tbuf);
      83  
      84  	if (-1L == res)
      85  		perror_msg_and_skip("times");
      86  	else
      87  		llres = (unsigned long) res;
      88  #endif
      89  
      90  	long clk_tck = sysconf(_SC_CLK_TCK);
      91  	int precision = clk_tck > 100000000 ? 9
      92  			: clk_tck > 10000000 ? 8
      93  			: clk_tck > 1000000 ? 7
      94  			: clk_tck > 100000 ? 6
      95  			: clk_tck > 10000 ? 5
      96  			: clk_tck > 1000 ? 4
      97  			: clk_tck > 100 ? 3
      98  			: clk_tck > 10 ? 2
      99  			: clk_tck > 1 ? 1 : 0;
     100  
     101  	if (!XLAT_RAW && clk_tck > 0) {
     102  		printf("times({tms_utime=%llu /* %.*f s */"
     103  		       ", tms_stime=%llu /* %.*f s */"
     104  		       ", tms_cutime=%llu /* %.*f s */"
     105  		       ", tms_cstime=%llu /* %.*f s */}) = %llu\n",
     106  		       (unsigned long long) tbuf.tms_utime,
     107  		       precision, (double) tbuf.tms_utime / clk_tck,
     108  		       (unsigned long long) tbuf.tms_stime,
     109  		       precision, (double) tbuf.tms_stime / clk_tck,
     110  		       (unsigned long long) tbuf.tms_cutime,
     111  		       precision, (double) tbuf.tms_cutime / clk_tck,
     112  		       (unsigned long long) tbuf.tms_cstime,
     113  		       precision, (double) tbuf.tms_cstime / clk_tck,
     114  		       llres);
     115  	} else {
     116  		printf("times({tms_utime=%llu, tms_stime=%llu"
     117  		       ", tms_cutime=%llu, tms_cstime=%llu}) = %llu\n",
     118  		       (unsigned long long) tbuf.tms_utime,
     119  		       (unsigned long long) tbuf.tms_stime,
     120  		       (unsigned long long) tbuf.tms_cutime,
     121  		       (unsigned long long) tbuf.tms_cstime,
     122  		       llres);
     123  	}
     124  
     125  	puts("+++ exited with 0 +++");
     126  
     127  	return 0;
     128  }