1 /* clock_nanosleep - high-resolution sleep with specifiable clock.
2 Copyright (C) 2002-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
23 #include <posix-timer.h>
24 #include <shlib-compat.h>
25 #include <sysdep-cancel.h>
28 nanosleep_call (const struct timespec
*req
, struct timespec
*rem
)
31 struct timespec before
;
34 const mach_msg_timeout_t ms
36 + (req
->tv_nsec
+ 999999) / 1000000;
38 recv
= __mach_reply_port ();
41 __clock_gettime (CLOCK_REALTIME
, &before
);
43 int cancel_oldtype
= LIBC_CANCEL_ASYNC();
44 err
= __mach_msg (NULL
, MACH_RCV_MSG
|MACH_RCV_TIMEOUT
|MACH_RCV_INTERRUPT
,
45 0, 0, recv
, ms
, MACH_PORT_NULL
);
46 LIBC_CANCEL_RESET (cancel_oldtype
);
48 __mach_port_destroy (mach_task_self (), recv
);
50 if (err
== EMACH_RCV_INTERRUPTED
)
54 struct timespec after
, elapsed
;
55 __clock_gettime (CLOCK_REALTIME
, &after
);
56 timespec_sub (&elapsed
, &after
, &before
);
57 timespec_sub (rem
, req
, &elapsed
);
67 __clock_nanosleep (clockid_t clock_id
, int flags
, const struct timespec
*req
,
70 if (clock_id
!= CLOCK_REALTIME
71 || !valid_nanoseconds (req
->tv_nsec
)
72 || (flags
!= 0 && flags
!= TIMER_ABSTIME
))
77 /* If we got an absolute time, remap it. */
78 if (flags
== TIMER_ABSTIME
)
83 /* Make sure we use safe data types. */
84 assert (sizeof (sec
) >= sizeof (now
.tv_sec
));
86 /* Get the current time for this clock. */
87 if (__clock_gettime (clock_id
, &now
) != 0)
90 /* Compute the difference. */
91 nsec
= req
->tv_nsec
- now
.tv_nsec
;
92 sec
= req
->tv_sec
- now
.tv_sec
- (nsec
< 0);
94 /* The time has already elapsed. */
98 now
.tv_nsec
= nsec
+ (nsec
< 0 ? 1000000000 : 0);
100 /* From now on this is our time. */
103 /* Make sure we are not modifying the struct pointed to by REM. */
107 return nanosleep_call (req
, rem
);
109 libc_hidden_def (__clock_nanosleep
)
110 versioned_symbol (libc
, __clock_nanosleep
, clock_nanosleep
, GLIBC_2_17
);
111 /* clock_nanosleep moved to libc in version 2.17;
112 old binaries may expect the symbol version it had in librt. */
113 #if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17)
114 strong_alias (__clock_nanosleep
, __clock_nanosleep_2
);
115 compat_symbol (libc
, __clock_nanosleep_2
, clock_nanosleep
, GLIBC_2_2
);