1/* Copyright (C) 1991-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18#include <errno.h>
19#include <time.h>
20#include <mach.h>
21#include <assert.h>
22#include <shlib-compat.h>
23
24/* Get the current time of day, putting it into *TS.
25 Returns 0 on success, -1 on errors. */
26int
27__clock_gettime (clockid_t clock_id, struct timespec *ts)
28{
29 mach_msg_type_number_t count;
30 error_t err;
31
32 switch (clock_id) {
33
34 case CLOCK_REALTIME:
35 {
36 /* __host_get_time can only fail if passed an invalid host_t.
37 __mach_host_self could theoretically fail (producing an
38 invalid host_t) due to resource exhaustion, but we assume
39 this will never happen. */
40 time_value_t tv;
41 __host_get_time (__mach_host_self (), &tv);
42 TIME_VALUE_TO_TIMESPEC (&tv, ts);
43 return 0;
44 }
45
46 case CLOCK_PROCESS_CPUTIME_ID:
47 {
48 struct time_value t = { .seconds = 0, .microseconds = 0 };
49 struct task_basic_info bi;
50 struct task_thread_times_info tti;
51
52 /* Dead threads CPU time. */
53 count = TASK_BASIC_INFO_COUNT;
54 err = __task_info (__mach_task_self (), TASK_BASIC_INFO,
55 (task_info_t) &bi, &count);
56 if (err)
57 {
58 __set_errno(err);
59 return -1;
60 }
61 time_value_add (&t, &bi.user_time);
62 time_value_add (&t, &bi.system_time);
63
64 /* Live threads CPU time. */
65 count = TASK_EVENTS_INFO_COUNT;
66 err = __task_info (__mach_task_self (), TASK_THREAD_TIMES_INFO,
67 (task_info_t) &tti, &count);
68 if (err)
69 {
70 __set_errno(err);
71 return -1;
72 }
73 time_value_add (&t, &tti.user_time);
74 time_value_add (&t, &tti.system_time);
75
76 TIME_VALUE_TO_TIMESPEC(&t, ts);
77 return 0;
78 }
79
80 case CLOCK_THREAD_CPUTIME_ID:
81 {
82 struct thread_basic_info bi;
83 mach_port_t self = __mach_thread_self ();
84
85 count = THREAD_BASIC_INFO_COUNT;
86 err = __thread_info (self, THREAD_BASIC_INFO,
87 (thread_info_t) &bi, &count);
88 __mach_port_deallocate (__mach_task_self (), self);
89 if (err)
90 {
91 __set_errno(err);
92 return -1;
93 }
94 time_value_add (&bi.user_time, &bi.system_time);
95
96 TIME_VALUE_TO_TIMESPEC(&bi.user_time, ts);
97 return 0;
98 }
99 }
100
101 errno = EINVAL;
102 return -1;
103}
104libc_hidden_def (__clock_gettime)
105
106versioned_symbol (libc, __clock_gettime, clock_gettime, GLIBC_2_17);
107/* clock_gettime moved to libc in version 2.17;
108 old binaries may expect the symbol version it had in librt. */
109#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17)
110strong_alias (__clock_gettime, __clock_gettime_2);
111compat_symbol (libc, __clock_gettime_2, clock_gettime, GLIBC_2_2);
112#endif
113
114int
115__clock_gettime64 (clockid_t clock_id, struct __timespec64 *ts64)
116{
117 struct timespec ts;
118 int ret;
119
120 ret = __clock_gettime (clock_id, &ts);
121 if (ret == 0)
122 *ts64 = valid_timespec_to_timespec64 (ts);
123
124 return ret;
125}
126libc_hidden_def (__clock_gettime64)
127

source code of glibc/sysdeps/mach/clock_gettime.c