Revision: 143 http://trac.macosforge.org/projects/libdispatch/changeset/143 Author: dsteffen@apple.com Date: 2009-11-09 17:28:43 -0800 (Mon, 09 Nov 2009) Log Message: ----------- consolidate & simplify mach<>nano conversion functions fix link error on non-intel platforms with mach timebase Modified Paths: -------------- trunk/libdispatch.xcodeproj/project.pbxproj trunk/src/shims/time.c trunk/src/shims/time.h trunk/src/source.c trunk/src/time.c trunk/testing/dispatch_starfish.c Modified: trunk/libdispatch.xcodeproj/project.pbxproj =================================================================== --- trunk/libdispatch.xcodeproj/project.pbxproj 2009-11-06 22:41:12 UTC (rev 142) +++ trunk/libdispatch.xcodeproj/project.pbxproj 2009-11-10 01:28:43 UTC (rev 143) @@ -27,6 +27,7 @@ 96BC39BD0F3EBAB100C59689 /* queue_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 96BC39BC0F3EBAB100C59689 /* queue_private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 96C9553B0F3EAEDD000D2CA4 /* once.h in Headers */ = {isa = PBXBuildFile; fileRef = 96C9553A0F3EAEDD000D2CA4 /* once.h */; settings = {ATTRIBUTES = (Public, ); }; }; 96DF70BE0F38FE3C0074BD99 /* once.c in Sources */ = {isa = PBXBuildFile; fileRef = 96DF70BD0F38FE3C0074BD99 /* once.c */; }; + E4BF990110A89607007655D0 /* time.c in Sources */ = {isa = PBXBuildFile; fileRef = E4BF990010A89607007655D0 /* time.c */; }; FC0B34790FA2851C0080FFA0 /* source_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = FC0B34780FA2851C0080FFA0 /* source_internal.h */; }; FC18329F109923A7003403D5 /* mach.c in Sources */ = {isa = PBXBuildFile; fileRef = FC18329E109923A7003403D5 /* mach.c */; }; FC1832A6109923C7003403D5 /* perfmon.h in Headers */ = {isa = PBXBuildFile; fileRef = FC1832A2109923C7003403D5 /* perfmon.h */; }; @@ -74,6 +75,7 @@ 96C9553A0F3EAEDD000D2CA4 /* once.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = once.h; path = dispatch/once.h; sourceTree = "<group>"; }; 96DF70BD0F38FE3C0074BD99 /* once.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = once.c; path = src/once.c; sourceTree = "<group>"; }; D2AAC046055464E500DB518D /* libdispatch.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdispatch.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E4BF990010A89607007655D0 /* time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = time.c; path = src/shims/time.c; sourceTree = "<group>"; }; FC0B34780FA2851C0080FFA0 /* source_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = source_internal.h; path = src/source_internal.h; sourceTree = "<group>"; }; FC18329E109923A7003403D5 /* mach.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mach.c; path = src/shims/mach.c; sourceTree = "<group>"; }; FC1832A2109923C7003403D5 /* perfmon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = perfmon.h; path = src/shims/perfmon.h; sourceTree = "<group>"; }; @@ -172,6 +174,7 @@ isa = PBXGroup; children = ( FC18329E109923A7003403D5 /* mach.c */, + E4BF990010A89607007655D0 /* time.c */, ); name = shims; sourceTree = "<group>"; @@ -382,6 +385,7 @@ 96A8AA870F41E7A400CD570B /* source.c in Sources */, 96032E4B0F5CC8C700241C5F /* time.c in Sources */, FC18329F109923A7003403D5 /* mach.c in Sources */, + E4BF990110A89607007655D0 /* time.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Modified: trunk/src/shims/time.c =================================================================== --- trunk/src/shims/time.c 2009-11-06 22:41:12 UTC (rev 142) +++ trunk/src/shims/time.c 2009-11-10 01:28:43 UTC (rev 143) @@ -18,50 +18,19 @@ * @APPLE_APACHE_LICENSE_HEADER_END@ */ +#include "internal.h" + // for architectures that don't always return mach_absolute_time() in nanoseconds -#if !defined(__i386__) && !defined(__x86_64__) && defined(HAVE_MACH_ABSOLUTE_TIME) -static mach_timebase_info_data_t tbi; -static dispatch_once_t tbi_pred; +#if !(defined(__i386__) || defined(__x86_64__) || !defined(HAVE_MACH_ABSOLUTE_TIME)) +_dispatch_host_time_data_s _dispatch_host_time_data; -static void -_dispatch_convert_init(void *context __attribute__((unused))) +void +_dispatch_get_host_time_init(void *context __attribute__((unused))) { - dispatch_assume_zero(mach_timebase_info(&tbi)); + mach_timebase_info_data_t tbi; + (void)dispatch_assume_zero(mach_timebase_info(&tbi)); + _dispatch_host_time_data.frac = tbi.numer; + _dispatch_host_time_data.frac /= tbi.denom; + _dispatch_host_time_data.ratio_1_to_1 = (tbi.numer == tbi.denom); } - -uint64_t -_dispatch_convert_mach2nano(uint64_t val) -{ -#ifdef __LP64__ - __uint128_t tmp; -#else - long double tmp; #endif - - dispatch_once_f(&tbi_pred, NULL, _dispatch_convert_init); - - tmp = val; - tmp *= tbi.numer; - tmp /= tbi.denom; - - return tmp; -} - -uint64_t -_dispatch_convert_nano2mach(uint64_t val) -{ -#ifdef __LP64__ - __uint128_t tmp; -#else - long double tmp; -#endif - - dispatch_once_f(&tbi_pred, NULL, _dispatch_convert_init); - - tmp = val; - tmp *= tbi.denom; - tmp /= tbi.numer; - - return tmp; -} -#endif Modified: trunk/src/shims/time.h =================================================================== --- trunk/src/shims/time.h 2009-11-06 22:41:12 UTC (rev 142) +++ trunk/src/shims/time.h 2009-11-10 01:28:43 UTC (rev 143) @@ -27,13 +27,56 @@ #ifndef __DISPATCH_SHIMS_TIME__ #define __DISPATCH_SHIMS_TIME__ +#ifndef __DISPATCH_INDIRECT__ +#error "Please #include <dispatch/dispatch.h> instead of this file directly." +#endif + #if defined(__i386__) || defined(__x86_64__) || !defined(HAVE_MACH_ABSOLUTE_TIME) // these architectures always return mach_absolute_time() in nanoseconds -#define _dispatch_convert_mach2nano(x) (x) -#define _dispatch_convert_nano2mach(x) (x) +#define _dispatch_time_mach2nano(x) (x) +#define _dispatch_time_nano2mach(x) (x) #else -extern uint64_t _dispatch_convert_mach2nano(uint64_t val); -extern uint64_t _dispatch_convert_nano2mach(uint64_t val); +typedef struct _dispatch_host_time_data_s { + long double frac; + bool ratio_1_to_1; + dispatch_once_t pred; +} _dispatch_host_time_data_s; +__private_extern__ _dispatch_host_time_data_s _dispatch_host_time_data; +__private_extern__ 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); + + return machtime * data->frac; +} + +static inline int64_t +_dispatch_time_nano2mach(int64_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 (slowpath(_dispatch_host_time_data.ratio_1_to_1)) { + return nsec; + } + + long double big_tmp = nsec; + + // Divide by tbi.numer/tbi.denom to convert nsec to Mach absolute time + big_tmp /= data->frac; + + // Clamp to a 64bit signed int + if (slowpath(big_tmp > INT64_MAX)) { + return INT64_MAX; + } + if (slowpath(big_tmp < INT64_MIN)) { + return INT64_MIN; + } + return big_tmp; +} #endif static inline uint64_t Modified: trunk/src/source.c =================================================================== --- trunk/src/source.c 2009-11-06 22:41:12 UTC (rev 142) +++ trunk/src/source.c 2009-11-10 01:28:43 UTC (rev 143) @@ -1511,7 +1511,7 @@ // verified that the target is greater than now. delta_tmp = ds->ds_timer.target - now; if (!(ds->ds_timer.flags & DISPATCH_TIMER_WALL_CLOCK)) { - delta_tmp = _dispatch_convert_mach2nano(delta_tmp); + delta_tmp = _dispatch_time_mach2nano(delta_tmp); } if (delta_tmp < delta) { delta = delta_tmp; @@ -1572,6 +1572,9 @@ } else if (start == DISPATCH_TIME_FOREVER) { start = INT64_MAX; } + if ((int64_t)leeway < 0) { + leeway = INT64_MAX; + } while (!(params = malloc(sizeof(struct dispatch_set_timer_params)))) { sleep(1); @@ -1593,8 +1596,8 @@ params->ident = DISPATCH_TIMER_INDEX_MACH; params->values.start = start; params->values.target = start; - params->values.interval = _dispatch_convert_nano2mach(interval); - params->values.leeway = _dispatch_convert_nano2mach(leeway); + params->values.interval = _dispatch_time_nano2mach(interval); + params->values.leeway = _dispatch_time_nano2mach(leeway); params->values.flags &= ~DISPATCH_TIMER_WALL_CLOCK; } @@ -1633,7 +1636,7 @@ if (ds->ds_timer.flags & DISPATCH_TIMER_WALL_CLOCK) { return ds->ds_timer.interval; } else { - return _dispatch_convert_mach2nano(ds->ds_timer.interval); + return _dispatch_time_mach2nano(ds->ds_timer.interval); } } #endif /* DISPATCH_NO_LEGACY */ Modified: trunk/src/time.c =================================================================== --- trunk/src/time.c 2009-11-06 22:41:12 UTC (rev 142) +++ trunk/src/time.c 2009-11-10 01:28:43 UTC (rev 143) @@ -31,81 +31,6 @@ return now.tv_sec * NSEC_PER_SEC + now.tv_usec * NSEC_PER_USEC; } -#if defined(__i386__) || defined(__x86_64__) -// x86 currently implements mach time in nanoseconds; this is NOT likely to change -#define _dispatch_time_mach2nano(x) (x) -#define _dispatch_time_nano2mach(x) (x) -#else -static struct _dispatch_host_time_data_s { - mach_timebase_info_data_t tbi; - uint64_t safe_numer_math; - dispatch_once_t pred; -} _dispatch_host_time_data; - -static void -_dispatch_get_host_time_init(void *context __attribute__((unused))) -{ - (void)dispatch_assume_zero(mach_timebase_info( - &_dispatch_host_time_data.tbi)); - _dispatch_host_time_data.safe_numer_math = DISPATCH_TIME_FOREVER / _dispatch_host_time_data.tbi.numer; -} - -static uint64_t -_dispatch_time_mach2nano(uint64_t nsec) -{ - struct _dispatch_host_time_data_s *const data = &_dispatch_host_time_data; - uint64_t small_tmp = nsec; -#ifdef __LP64__ - __uint128_t big_tmp = nsec; -#else - long double big_tmp = nsec; -#endif - - dispatch_once_f(&data->pred, NULL, _dispatch_get_host_time_init); - - if (slowpath(data->tbi.numer != data->tbi.denom)) { - if (nsec < data->safe_numer_math) { - small_tmp *= data->tbi.numer; - small_tmp /= data->tbi.denom; - } else { - big_tmp *= data->tbi.numer; - big_tmp /= data->tbi.denom; - small_tmp = big_tmp; - } - } - return small_tmp; -} - -static int64_t -_dispatch_time_nano2mach(int64_t nsec) -{ - struct _dispatch_host_time_data_s *const data = &_dispatch_host_time_data; -#ifdef __LP64__ - __int128_t big_tmp = nsec; -#else - long double big_tmp = nsec; -#endif - - dispatch_once_f(&data->pred, NULL, _dispatch_get_host_time_init); - - if (fastpath(data->tbi.numer == data->tbi.denom)) { - return nsec; - } - - // Multiply by the inverse to convert nsec to Mach absolute time - big_tmp *= data->tbi.denom; - big_tmp /= data->tbi.numer; - - if (big_tmp > INT64_MAX) { - return INT64_MAX; - } - if (big_tmp < INT64_MIN) { - return INT64_MIN; - } - return big_tmp; -} -#endif - dispatch_time_t dispatch_time(dispatch_time_t inval, int64_t delta) { Modified: trunk/testing/dispatch_starfish.c =================================================================== --- trunk/testing/dispatch_starfish.c 2009-11-06 22:41:12 UTC (rev 142) +++ trunk/testing/dispatch_starfish.c 2009-11-10 01:28:43 UTC (rev 143) @@ -58,7 +58,7 @@ } delta = _dispatch_absolute_time() - start; - math = delta = _dispatch_convert_mach2nano(delta); + math = delta = _dispatch_time_mach2nano(delta); math /= COUNT * COUNT * 2ul + COUNT * 2ul; printf("lap: %ld\n", lap_count_down);
participants (1)
-
source_changes@macosforge.org