blob: 7b297711c9553e6c979a156d22d5aa6b7ed0d0f2 [file] [log] [blame]
/*
* Copyright (c) 2008-2013 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
* IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
* which are subject to change in future releases of Mac OS X. Any applications
* relying on these interfaces WILL break.
*/
#ifndef __DISPATCH_SHIMS_TIME__
#define __DISPATCH_SHIMS_TIME__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#endif
#if TARGET_OS_WIN32
static inline unsigned int
sleep(unsigned int seconds)
{
Sleep(seconds * 1000); // milliseconds
return 0;
}
#endif
uint64_t _dispatch_get_nanoseconds(void);
#if defined(__i386__) || defined(__x86_64__) || !HAVE_MACH_ABSOLUTE_TIME
// x86 currently implements mach time in nanoseconds
// this is NOT likely to change
DISPATCH_ALWAYS_INLINE
static inline uint64_t
_dispatch_time_mach2nano(uint64_t machtime)
{
return machtime;
}
DISPATCH_ALWAYS_INLINE
static inline uint64_t
_dispatch_time_nano2mach(uint64_t nsec)
{
return nsec;
}
#else
typedef struct _dispatch_host_time_data_s {
dispatch_once_t pred;
long double frac;
bool ratio_1_to_1;
} _dispatch_host_time_data_s;
extern _dispatch_host_time_data_s _dispatch_host_time_data;
void _dispatch_get_host_time_init(void *context);
static inline uint64_t
_dispatch_time_mach2nano(uint64_t machtime)
{
_dispatch_host_time_data_s *const data = &_dispatch_host_time_data;
dispatch_once_f(&data->pred, NULL, _dispatch_get_host_time_init);
if (!machtime || slowpath(data->ratio_1_to_1)) {
return machtime;
}
if (machtime >= INT64_MAX) {
return INT64_MAX;
}
long double big_tmp = ((long double)machtime * data->frac) + .5;
if (slowpath(big_tmp >= INT64_MAX)) {
return INT64_MAX;
}
return (uint64_t)big_tmp;
}
static inline uint64_t
_dispatch_time_nano2mach(uint64_t nsec)
{
_dispatch_host_time_data_s *const data = &_dispatch_host_time_data;
dispatch_once_f(&data->pred, NULL, _dispatch_get_host_time_init);
if (!nsec || slowpath(data->ratio_1_to_1)) {
return nsec;
}
if (nsec >= INT64_MAX) {
return INT64_MAX;
}
long double big_tmp = ((long double)nsec / data->frac) + .5;
if (slowpath(big_tmp >= INT64_MAX)) {
return INT64_MAX;
}
return (uint64_t)big_tmp;
}
#endif
static inline uint64_t
_dispatch_absolute_time(void)
{
#if HAVE_MACH_ABSOLUTE_TIME
return mach_absolute_time();
#elif TARGET_OS_WIN32
LARGE_INTEGER now;
return QueryPerformanceCounter(&now) ? now.QuadPart : 0;
#else
struct timespec ts;
int ret;
#if HAVE_DECL_CLOCK_UPTIME
ret = clock_gettime(CLOCK_UPTIME, &ts);
#elif HAVE_DECL_CLOCK_MONOTONIC
ret = clock_gettime(CLOCK_MONOTONIC, &ts);
#else
#error "clock_gettime: no supported absolute time clock"
#endif
(void)dispatch_assume_zero(ret);
/* XXXRW: Some kind of overflow detection needed? */
return (ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec);
#endif // HAVE_MACH_ABSOLUTE_TIME
}
static inline uint64_t
_dispatch_approximate_time(void)
{
return _dispatch_absolute_time();
}
#endif // __DISPATCH_SHIMS_TIME__