From 262e0a636b40816127403066159df9c3e3791d9a Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 7 Jan 2006 23:05:56 +0000 Subject: [PATCH] We use the same strategy for computing the system time as on x86 now. The time base conversion factor is the 32 bit value 2^32 * 1000000 / time base frequency, so the system time can be computed by system time = time base * conversion factor / 2^32. The expression in system_time() looks more complicated now, but is actually much faster (factor 2.5 on my Mac mini). I'm positively surprised, how good the assembly looks, that GCC 4 generates. There's not that much potential for optimization by hand-coding the function. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15863 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/ppc/arch_cpu.h | 2 +- .../kernel/arch/ppc/arch_real_time_data.h | 2 +- .../kernel/arch/ppc/arch_real_time_clock.cpp | 6 +++++- src/system/libroot/os/arch/ppc/system_time.c | 16 +++++----------- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/headers/private/kernel/arch/ppc/arch_cpu.h b/headers/private/kernel/arch/ppc/arch_cpu.h index 18ef2b81c6..bce4c06af1 100644 --- a/headers/private/kernel/arch/ppc/arch_cpu.h +++ b/headers/private/kernel/arch/ppc/arch_cpu.h @@ -105,7 +105,7 @@ extern void reset_dbats(void); //extern void setl2cr(unsigned int val); extern long long get_time_base(void); -void __ppc_setup_system_time(vint64 *cvFactor); +void __ppc_setup_system_time(vint32 *cvFactor); // defined in libroot: os/arch/system_time.c int64 __ppc_get_time_base(void); // defined in libroot: os/arch/system_time_asm.S diff --git a/headers/private/kernel/arch/ppc/arch_real_time_data.h b/headers/private/kernel/arch/ppc/arch_real_time_data.h index c1e88cd381..d3d2f07d7c 100644 --- a/headers/private/kernel/arch/ppc/arch_real_time_data.h +++ b/headers/private/kernel/arch/ppc/arch_real_time_data.h @@ -15,7 +15,7 @@ struct ppc_real_time_data { struct arch_real_time_data { struct ppc_real_time_data data[2]; - vint64 system_time_conversion_factor; + vint32 system_time_conversion_factor; vint32 version; // Since there're no cheap atomic_{set,get,add}64() on PPC 32 (i.e. one // that doesn't involve a syscall), we can't have just a single diff --git a/src/system/kernel/arch/ppc/arch_real_time_clock.cpp b/src/system/kernel/arch/ppc/arch_real_time_clock.cpp index 463ed511c7..a16f346895 100644 --- a/src/system/kernel/arch/ppc/arch_real_time_clock.cpp +++ b/src/system/kernel/arch/ppc/arch_real_time_clock.cpp @@ -22,8 +22,12 @@ arch_rtc_init(kernel_args *args, struct real_time_data *data) // init the arch specific part of the real_time_data data->arch_data.data[0].system_time_offset = 0; + // cvFactor = 2^32 * 1000000 / tbFreq + // => (tb * cvFactor) >> 32 = (tb * 2^32 * 1000000 / tbFreq) >> 32 + // = tb / tbFreq * 1000000 = time in us data->arch_data.system_time_conversion_factor - = args->arch_args.time_base_frequency; + = uint32((uint64(1) << 32) * 1000000 + / args->arch_args.time_base_frequency); data->arch_data.version = 0; // init spinlock diff --git a/src/system/libroot/os/arch/ppc/system_time.c b/src/system/libroot/os/arch/ppc/system_time.c index 8eecc81a60..b1f1a96b88 100644 --- a/src/system/libroot/os/arch/ppc/system_time.c +++ b/src/system/libroot/os/arch/ppc/system_time.c @@ -10,10 +10,10 @@ #include -static vint64 *sConversionFactor; +static vint32 *sConversionFactor; void -__ppc_setup_system_time(vint64 *cvFactor) +__ppc_setup_system_time(vint32 *cvFactor) { sConversionFactor = cvFactor; } @@ -26,13 +26,7 @@ bigtime_t system_time(void) { uint64 timeBase = __ppc_get_time_base(); - // TODO: The multiplication doesn't look that nice. The value can easily - // overflow when timeBase gets big enough. The limit for timebase is - // about 2^(64 - 20). This might sound a lot, but the conversion factor - // might be quite big. Assuming a worst case factor of 2^32, - // this would leave us with only about 2^12 = 4096 seconds we can - // represent. The actual factor for my Mac mini is about 40 * 10^6, i.e. - // the overflow limit is ca. 100 times greater, but that isn't more than - // five days either. - return (timeBase * 1000000ULL) / *sConversionFactor; + + uint32 cv = *sConversionFactor; + return (timeBase >> 32) * cv + (((timeBase & 0xffffffff) * cv) >> 32); }