blob: 704c574028c308a0e4aba1277fc590b608389139 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* clock_getcpuclockid -- Get a clockid_t for process CPU time. Linux version.
2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20#include <errno.h>
21#include <time.h>
22#include <sysdep.h>
23#include <unistd.h>
24#include <bits/kernel-features.h>
25#include "kernel-posix-cpu-timers.h"
26
27#ifndef HAS_CPUCLOCK
28# define HAS_CPUCLOCK 1
29#endif
30
31int
32clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
33{
34#ifdef __NR_clock_getres
35 /* The clockid_t value is a simple computation from the PID.
36 But we do a clock_getres call to validate it. */
37
38 const clockid_t pidclock = MAKE_PROCESS_CPUCLOCK (pid, CPUCLOCK_SCHED);
39
40# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
41 extern int __libc_missing_posix_cpu_timers attribute_hidden;
42# if !(__ASSUME_POSIX_TIMERS > 0)
43 extern int __libc_missing_posix_timers attribute_hidden;
44 if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers)
45 __libc_missing_posix_cpu_timers = 1;
46# endif
47 if (!__libc_missing_posix_cpu_timers)
48# endif
49 {
50 INTERNAL_SYSCALL_DECL (err);
51 int r = INTERNAL_SYSCALL (clock_getres, err, 2, pidclock, NULL);
52 if (!INTERNAL_SYSCALL_ERROR_P (r, err))
53 {
54 *clock_id = pidclock;
55 return 0;
56 }
57
58# if !(__ASSUME_POSIX_TIMERS > 0)
59 if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
60 {
61 /* The kernel doesn't support these calls at all. */
62 __libc_missing_posix_timers = 1;
63 __libc_missing_posix_cpu_timers = 1;
64 }
65 else
66# endif
67 if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL)
68 {
69# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
70 if (pidclock == MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED)
71 || INTERNAL_SYSCALL_ERROR_P (INTERNAL_SYSCALL
72 (clock_getres, err, 2,
73 MAKE_PROCESS_CPUCLOCK
74 (0, CPUCLOCK_SCHED), NULL),
75 err))
76 /* The kernel doesn't support these clocks at all. */
77 __libc_missing_posix_cpu_timers = 1;
78 else
79# endif
80 /* The clock_getres system call checked the PID for us. */
81 return ESRCH;
82 }
83 else
84 return INTERNAL_SYSCALL_ERRNO (r, err);
85 }
86#endif
87
88 /* We don't allow any process ID but our own. */
89 if (pid != 0 && pid != getpid ())
90 return EPERM;
91
92#ifdef CLOCK_PROCESS_CPUTIME_ID
93 if (HAS_CPUCLOCK)
94 {
95 /* Store the number. */
96 *clock_id = CLOCK_PROCESS_CPUTIME_ID;
97
98 return 0;
99 }
100#endif
101
102 /* We don't have a timer for that. */
103 return ENOENT;
104}