VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/semwait.h@ 103795

Last change on this file since 103795 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.4 KB
Line 
1/* $Id: semwait.h 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Common semaphore wait code.
4 */
5
6/*
7 * Copyright (C) 2021-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37#ifndef IPRT_INCLUDED_SRC_r3_posix_semwait_h
38#define IPRT_INCLUDED_SRC_r3_posix_semwait_h
39#ifndef RT_WITHOUT_PRAGMA_ONCE
40# pragma once
41#endif
42
43
44/** @def IPRT_HAVE_PTHREAD_CONDATTR_SETCLOCK
45 * Set if the platform implements pthread_condattr_setclock().
46 * Enables the use of the monotonic clock for waiting on condition variables. */
47#ifndef IPRT_HAVE_PTHREAD_CONDATTR_SETCLOCK
48/* Linux detection */
49# if defined(RT_OS_LINUX) && defined(__USE_XOPEN2K)
50# include <features.h>
51# if __GLIBC_PREREQ(2,6) /** @todo figure the exact version where this was added */
52# define IPRT_HAVE_PTHREAD_CONDATTR_SETCLOCK
53# endif
54# endif
55/** @todo check other platforms */
56#endif
57
58
59/**
60 * Converts a extended wait timeout specification to an absolute timespec and a
61 * relative nanosecond count.
62 *
63 * @note This does not check for RTSEMWAIT_FLAGS_INDEFINITE, caller should've
64 * done that already.
65 *
66 * @returns The relative wait in nanoseconds. 0 for a poll call, UINT64_MAX for
67 * an effectively indefinite wait.
68 * @param fFlags RTSEMWAIT_FLAGS_XXX.
69 * @param fMonotonicClock Whether the timeout is in monotonic (true) or real
70 * (false) time.
71 * @param uTimeout The timeout.
72 * @param pAbsDeadline Where to return the absolute deadline.
73 */
74DECLINLINE(uint64_t) rtSemPosixCalcDeadline(uint32_t fFlags, uint64_t uTimeout, bool fMonotonicClock,
75 struct timespec *pAbsDeadline)
76{
77 Assert(!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE));
78
79 /*
80 * Convert uTimeout to a relative value in nanoseconds.
81 */
82 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
83 {
84 if (uTimeout < UINT64_MAX / RT_NS_1MS)
85 uTimeout = uTimeout * RT_NS_1MS;
86 else
87 return UINT64_MAX;
88 }
89 else if (uTimeout == UINT64_MAX) /* unofficial way of indicating an indefinite wait */
90 return UINT64_MAX;
91
92 /*
93 * Make uTimeout relative and check for polling (zero timeout) calls.
94 */
95 uint64_t uAbsTimeout = uTimeout;
96 if (fFlags & RTSEMWAIT_FLAGS_ABSOLUTE)
97 {
98 uint64_t const u64Now = RTTimeSystemNanoTS();
99 if (uTimeout > u64Now)
100 uTimeout -= u64Now;
101 else
102 return 0;
103 }
104 else if (uTimeout == 0)
105 return 0;
106
107 /*
108 * Calculate the deadline according to the clock we're using.
109 */
110 if (!fMonotonicClock)
111 {
112#if defined(RT_OS_DARWIN) || defined(RT_OS_HAIKU)
113 struct timeval tv = {0,0};
114 gettimeofday(&tv, NULL);
115 pAbsDeadline->tv_sec = tv.tv_sec;
116 pAbsDeadline->tv_nsec = tv.tv_usec * 1000;
117#else
118 clock_gettime(CLOCK_REALTIME, pAbsDeadline);
119#endif
120 struct timespec TsAdd;
121 TsAdd.tv_nsec = uTimeout % RT_NS_1SEC;
122 TsAdd.tv_sec = uTimeout / RT_NS_1SEC;
123
124 /* Check for 32-bit tv_sec overflows: */
125 if ( sizeof(pAbsDeadline->tv_sec) < sizeof(uint64_t)
126 && ( uTimeout >= (uint64_t)RT_NS_1SEC * UINT32_MAX
127 || (uint64_t)pAbsDeadline->tv_sec + pAbsDeadline->tv_sec >= UINT32_MAX) )
128 return UINT64_MAX;
129
130 pAbsDeadline->tv_sec += TsAdd.tv_sec;
131 pAbsDeadline->tv_nsec += TsAdd.tv_nsec;
132 if ((uint32_t)pAbsDeadline->tv_nsec >= RT_NS_1SEC)
133 {
134 pAbsDeadline->tv_nsec -= RT_NS_1SEC;
135 pAbsDeadline->tv_sec++;
136 }
137 }
138 else
139 {
140 /* ASSUMES RTTimeSystemNanoTS() == RTTimeNanoTS() == clock_gettime(CLOCK_MONOTONIC). */
141 if (fFlags & RTSEMWAIT_FLAGS_RELATIVE)
142 {
143 uint64_t const nsNow = RTTimeSystemNanoTS();
144 uAbsTimeout += nsNow;
145 if (uAbsTimeout < nsNow)
146 return UINT64_MAX;
147 }
148
149 /* Check for 32-bit tv_sec overflows: */
150 if ( sizeof(pAbsDeadline->tv_sec) < sizeof(uint64_t)
151 && uAbsTimeout >= (uint64_t)RT_NS_1SEC * UINT32_MAX)
152 return UINT64_MAX;
153
154 pAbsDeadline->tv_nsec = uAbsTimeout % RT_NS_1SEC;
155 pAbsDeadline->tv_sec = uAbsTimeout / RT_NS_1SEC;
156 }
157
158 return uTimeout;
159}
160
161#endif /* !IPRT_INCLUDED_SRC_r3_posix_semwait_h */
162
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette