From 34a48c70efb9ce4fd54db2ef76d95e9c2ff9ec2e Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 7 Dec 2009 21:43:19 +0000 Subject: [PATCH] Added type nanotime_t (an int64 storing a nanoseconds value) and function system_time_nsecs(), returning the system time in nanoseconds. The function is only really implemented for x86. For the other architectures system_time() * 1000 is returned. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34543 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/kernel/OS.h | 3 +- headers/os/support/SupportDefs.h | 1 + headers/private/kernel/arch/x86/arch_cpu.h | 3 +- src/system/kernel/arch/x86/arch_cpu.cpp | 14 ++- src/system/kernel/lib/arch/arm/Jamfile | 3 + src/system/kernel/lib/arch/m68k/Jamfile | 3 + src/system/kernel/lib/arch/mipsel/Jamfile | 3 + src/system/kernel/lib/arch/ppc/Jamfile | 3 + src/system/libroot/os/arch/m68k/Jamfile | 4 + src/system/libroot/os/arch/mipsel/Jamfile | 4 + src/system/libroot/os/arch/ppc/Jamfile | 4 + .../libroot/os/arch/x86/system_time_asm.S | 107 ++++++++++++++++-- src/system/libroot/os/arch/x86/time.c | 18 ++- 13 files changed, 155 insertions(+), 15 deletions(-) diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h index 22647f36d2..398adb1557 100644 --- a/headers/os/kernel/OS.h +++ b/headers/os/kernel/OS.h @@ -367,7 +367,8 @@ extern bigtime_t real_time_clock_usecs(void); extern status_t set_timezone(const char *timezone); extern bigtime_t system_time(void); /* time since booting in microseconds */ - +extern nanotime_t system_time_nsecs(); + /* time since booting in nanoseconds */ /* Alarm */ diff --git a/headers/os/support/SupportDefs.h b/headers/os/support/SupportDefs.h index 401d5d99d2..4aa4248f59 100644 --- a/headers/os/support/SupportDefs.h +++ b/headers/os/support/SupportDefs.h @@ -52,6 +52,7 @@ typedef unsigned short unichar; /* descriptive types */ typedef int32 status_t; typedef int64 bigtime_t; +typedef int64 nanotime_t; typedef uint32 type_code; typedef uint32 perform_code; diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 69b1d5a302..c3efa42d89 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -262,7 +262,8 @@ extern "C" { struct arch_thread; -void __x86_setup_system_time(uint32 conversionFactor); +void __x86_setup_system_time(uint32 conversionFactor, + uint32 conversionFactorNsecs, bool conversionFactorNsecsShift); void i386_context_switch(struct arch_thread* oldState, struct arch_thread* newState, addr_t newPageDir); void x86_userspace_thread_exit(void); diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index dd5e9bf8e8..3aeaff34b0 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -626,7 +626,19 @@ arch_cpu_init_percpu(kernel_args *args, int cpu) status_t arch_cpu_init(kernel_args *args) { - __x86_setup_system_time(args->arch_args.system_time_cv_factor); + // init the TSC -> system_time() conversion factors + + uint32 conversionFactor = args->arch_args.system_time_cv_factor; + uint64 conversionFactorNsecs = (uint64)conversionFactor * 1000; + + if (conversionFactorNsecs >> 32 != 0) { + // the TSC frequency is < 1 GHz, which forces us to shift the factor + __x86_setup_system_time(conversionFactor, conversionFactorNsecs >> 16, + true); + } else { + // the TSC frequency is >= 1 GHz + __x86_setup_system_time(conversionFactor, conversionFactorNsecs, false); + } return B_OK; } diff --git a/src/system/kernel/lib/arch/arm/Jamfile b/src/system/kernel/lib/arch/arm/Jamfile index 275696c9a2..084a552ca8 100644 --- a/src/system/kernel/lib/arch/arm/Jamfile +++ b/src/system/kernel/lib/arch/arm/Jamfile @@ -6,6 +6,7 @@ local librootSources = [ FDirName $(HAIKU_TOP) src system libroot ] ; local posixSources = [ FDirName $(librootSources) posix ] ; SEARCH_SOURCE += [ FDirName $(librootSources) os arch $(TARGET_ARCH) ] ; +SEARCH_SOURCE += [ FDirName $(librootSources) os arch generic ] ; KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o : atomic.S @@ -13,6 +14,8 @@ KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o : # system_time_asm.S system_time.c + generic_system_time_nsecs.cpp + : $(TARGET_KERNEL_PIC_CCFLAGS) ; diff --git a/src/system/kernel/lib/arch/m68k/Jamfile b/src/system/kernel/lib/arch/m68k/Jamfile index 1eb8793cbc..bdbb85424f 100644 --- a/src/system/kernel/lib/arch/m68k/Jamfile +++ b/src/system/kernel/lib/arch/m68k/Jamfile @@ -6,6 +6,7 @@ local librootSources = [ FDirName $(HAIKU_TOP) src system libroot ] ; local posixSources = [ FDirName $(librootSources) posix ] ; SEARCH_SOURCE += [ FDirName $(librootSources) os arch $(TARGET_ARCH) ] ; +SEARCH_SOURCE += [ FDirName $(librootSources) os arch generic ] ; KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o : atomic.S @@ -13,6 +14,8 @@ KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o : system_time_asm.S system_time.c + generic_system_time_nsecs.cpp + : $(TARGET_KERNEL_PIC_CCFLAGS) ; diff --git a/src/system/kernel/lib/arch/mipsel/Jamfile b/src/system/kernel/lib/arch/mipsel/Jamfile index 86c3cdb16a..4fc2ab87ac 100644 --- a/src/system/kernel/lib/arch/mipsel/Jamfile +++ b/src/system/kernel/lib/arch/mipsel/Jamfile @@ -6,6 +6,7 @@ local librootSources = [ FDirName $(HAIKU_TOP) src system libroot ] ; local posixSources = [ FDirName $(librootSources) posix ] ; SEARCH_SOURCE += [ FDirName $(librootSources) os arch $(TARGET_ARCH) ] ; +SEARCH_SOURCE += [ FDirName $(librootSources) os arch generic ] ; KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o : atomic.S @@ -13,6 +14,8 @@ KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o : system_time_asm.S system_time.c + generic_system_time_nsecs.cpp + : $(TARGET_KERNEL_PIC_CCFLAGS) ; diff --git a/src/system/kernel/lib/arch/ppc/Jamfile b/src/system/kernel/lib/arch/ppc/Jamfile index b7509ba3a3..028bff7ffb 100644 --- a/src/system/kernel/lib/arch/ppc/Jamfile +++ b/src/system/kernel/lib/arch/ppc/Jamfile @@ -6,6 +6,7 @@ local librootSources = [ FDirName $(HAIKU_TOP) src system libroot ] ; local posixSources = [ FDirName $(librootSources) posix ] ; SEARCH_SOURCE += [ FDirName $(librootSources) os arch $(TARGET_ARCH) ] ; +SEARCH_SOURCE += [ FDirName $(librootSources) os arch generic ] ; KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o : atomic.S @@ -13,6 +14,8 @@ KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o : system_time_asm.S system_time.c + generic_system_time_nsecs.cpp + : $(TARGET_KERNEL_PIC_CCFLAGS) ; diff --git a/src/system/libroot/os/arch/m68k/Jamfile b/src/system/libroot/os/arch/m68k/Jamfile index 0d8569f085..55f5ac22b5 100644 --- a/src/system/libroot/os/arch/m68k/Jamfile +++ b/src/system/libroot/os/arch/m68k/Jamfile @@ -3,6 +3,8 @@ SubDir HAIKU_TOP src system libroot os arch m68k ; UsePrivateKernelHeaders ; UsePrivateSystemHeaders ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; + MergeObject os_arch_$(TARGET_ARCH).o : atomic.S byteorder.S @@ -15,4 +17,6 @@ MergeObject os_arch_$(TARGET_ARCH).o : thread.c time.c tls.c + + generic_system_time_nsecs.cpp ; diff --git a/src/system/libroot/os/arch/mipsel/Jamfile b/src/system/libroot/os/arch/mipsel/Jamfile index b3260f6962..3b80e62b8a 100644 --- a/src/system/libroot/os/arch/mipsel/Jamfile +++ b/src/system/libroot/os/arch/mipsel/Jamfile @@ -5,6 +5,8 @@ UsePrivateKernelHeaders ; # time.c! UsePrivateSystemHeaders ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; + MergeObject os_arch_$(TARGET_ARCH).o : atomic.S byteorder.S @@ -17,4 +19,6 @@ MergeObject os_arch_$(TARGET_ARCH).o : thread.c time.c tls.c + + generic_system_time_nsecs.cpp ; diff --git a/src/system/libroot/os/arch/ppc/Jamfile b/src/system/libroot/os/arch/ppc/Jamfile index c361b868eb..3a293e7e1b 100644 --- a/src/system/libroot/os/arch/ppc/Jamfile +++ b/src/system/libroot/os/arch/ppc/Jamfile @@ -5,6 +5,8 @@ UsePrivateKernelHeaders ; # time.c! UsePrivateSystemHeaders ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; + MergeObject os_arch_$(TARGET_ARCH).o : atomic.S byteorder.S @@ -17,4 +19,6 @@ MergeObject os_arch_$(TARGET_ARCH).o : thread.c time.c tls.c + + generic_system_time_nsecs.cpp ; diff --git a/src/system/libroot/os/arch/x86/system_time_asm.S b/src/system/libroot/os/arch/x86/system_time_asm.S index 5447795b5e..9b579ea734 100644 --- a/src/system/libroot/os/arch/x86/system_time_asm.S +++ b/src/system/libroot/os/arch/x86/system_time_asm.S @@ -1,31 +1,43 @@ /* -** Copyright 2001, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ #include /* saves the conversion factor needed for system_time */ -.lcomm cv_factor 4 +.lcomm cv_factor 4 +.lcomm cv_factor_nsecs 4 +.lcomm cv_factor_nsecs_shift 1 .text + FUNCTION(__x86_setup_system_time): - movl 4(%esp),%eax - movl %eax,cv_factor + movl 4(%esp), %eax + movl %eax, cv_factor + movl 8(%esp), %eax + movl %eax, cv_factor_nsecs + movb 12(%esp), %al + movb %al, cv_factor_nsecs_shift ret FUNCTION_END(__x86_setup_system_time) -/* long long system_time(); */ -FUNCTION(system_time): - /* load 64-bit factor into %eax (low), %edx (high) */ - rdtsc /* time in %edx,%eax */ +/* int64 system_time(); */ +FUNCTION(system_time): pushl %ebx pushl %ecx movl cv_factor, %ebx + + /* load 64-bit factor into %eax (low), %edx (high) */ + rdtsc /* time in %edx,%eax */ + movl %edx, %ecx /* save high half */ mull %ebx /* truncate %eax, but keep %edx */ movl %ecx, %eax @@ -39,3 +51,78 @@ FUNCTION(system_time): popl %ebx ret FUNCTION_END(system_time) + + +/* int64 system_time_nsecs(); */ +FUNCTION(system_time_nsecs): + testb $0, cv_factor_nsecs_shift + jne 1f + + /* same algorithm as system_time(), just with a different factor */ + + pushl %ebx + pushl %ecx + movl cv_factor_nsecs, %ebx + + /* load 64-bit factor into %eax (low), %edx (high) */ + rdtsc /* time in %edx,%eax */ + + movl %edx, %ecx /* save high half */ + mull %ebx /* truncate %eax, but keep %edx */ + movl %ecx, %eax + movl %edx, %ecx /* save high half of low */ + mull %ebx /*, %eax*/ + /* now compute [%edx, %eax] + [%ecx], propagating carry */ + subl %ebx, %ebx /* need zero to propagate carry */ + addl %ecx, %eax + adc %ebx, %edx + popl %ecx + popl %ebx + ret + +1: + /* TSC frequency is less than 1 GHz -- we shift everything up 16 bit */ + + pushl %ebx + pushl %ecx + pushl %esi + movl cv_factor_nsecs, %ebx + + /* load 64-bit factor into %eax (low), %edx (high) */ + rdtsc /* time in %edx,%eax */ + + /* save high half */ + movl %edx, %ecx + + /* multiply low half by conversion factor */ + mull %ebx + + /* save result */ + movl %eax, %esi /* low half -> %esi */ + movl %ecx, %eax + movl %edx, %ecx /* high half -> %ecx */ + + /* multiply high half by conversion factor */ + mull %ebx + + /* now compute [%edx, %eax] + [%ecx], propagating carry */ + xorl %ebx, %ebx /* need zero to propagate carry */ + addl %ecx, %eax + adc %ebx, %edx + + /* shift the result left 16 bit */ + shl $16, %edx + movl %eax, %ebx + shr $16, %ebx + orw %bx, %dx + shl $16, %eax + + /* add the high 16 bit of the low half of the low product */ + shr $16, %esi + orw %si, %ax + + popl %esi + popl %ecx + popl %ebx + ret +FUNCTION_END(system_time_nsecs) diff --git a/src/system/libroot/os/arch/x86/time.c b/src/system/libroot/os/arch/x86/time.c index f1c29dd98d..3140eb5541 100644 --- a/src/system/libroot/os/arch/x86/time.c +++ b/src/system/libroot/os/arch/x86/time.c @@ -1,4 +1,4 @@ -/* +/* * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -12,6 +12,9 @@ void __arch_init_time(struct real_time_data *data, bool setDefaults) { + uint32 conversionFactor; + uint64 conversionFactorNsecs; + if (setDefaults) { data->arch_data.system_time_offset = 0; data->arch_data.system_time_conversion_factor = 100000; @@ -19,7 +22,18 @@ __arch_init_time(struct real_time_data *data, bool setDefaults) // TODO: this should only store a pointer to that value // When resolving this TODO, also resolve the one in the Jamfile. - __x86_setup_system_time(data->arch_data.system_time_conversion_factor); + + conversionFactor = data->arch_data.system_time_conversion_factor; + conversionFactorNsecs = (uint64)conversionFactor * 1000; + + if (conversionFactorNsecs >> 32 != 0) { + // the TSC frequency is < 1 GHz, which forces us to shift the factor + __x86_setup_system_time(conversionFactor, conversionFactorNsecs >> 16, + true); + } else { + // the TSC frequency is >= 1 GHz + __x86_setup_system_time(conversionFactor, conversionFactorNsecs, false); + } }