Implemented system_time() for x86_64.
* Uses 64-bit multiplication, special handling for CPUs clocked < 1 GHz in system_time_nsecs() not required like on x86. * Tested against a straight conversion of the x86 version, noticably faster with a large number of system_time() calls.
This commit is contained in:
parent
7444a55ce5
commit
5c7d52183c
@ -367,9 +367,14 @@ extern "C" {
|
||||
|
||||
struct arch_thread;
|
||||
|
||||
|
||||
#ifdef __x86_64__
|
||||
void __x86_setup_system_time(uint64 conversionFactor,
|
||||
uint64 conversionFactorNsecs);
|
||||
#else
|
||||
void __x86_setup_system_time(uint32 conversionFactor,
|
||||
uint32 conversionFactorNsecs, bool conversionFactorNsecsShift);
|
||||
#endif
|
||||
|
||||
void x86_context_switch(struct arch_thread* oldState,
|
||||
struct arch_thread* newState);
|
||||
void x86_userspace_thread_exit(void);
|
||||
|
@ -820,6 +820,12 @@ arch_cpu_init(kernel_args* args)
|
||||
uint32 conversionFactor = args->arch_args.system_time_cv_factor;
|
||||
uint64 conversionFactorNsecs = (uint64)conversionFactor * 1000;
|
||||
|
||||
#ifdef __x86_64__
|
||||
// The x86_64 system_time() implementation uses 64-bit multiplication and
|
||||
// therefore shifting is not necessary for low frequencies (it's also not
|
||||
// too likely that there'll be any x86_64 CPUs clocked under 1GHz).
|
||||
__x86_setup_system_time(conversionFactor, conversionFactorNsecs);
|
||||
#else
|
||||
if (conversionFactorNsecs >> 32 != 0) {
|
||||
// the TSC frequency is < 1 GHz, which forces us to shift the factor
|
||||
__x86_setup_system_time(conversionFactor, conversionFactorNsecs >> 16,
|
||||
@ -828,6 +834,7 @@ arch_cpu_init(kernel_args* args)
|
||||
// the TSC frequency is >= 1 GHz
|
||||
__x86_setup_system_time(conversionFactor, conversionFactorNsecs, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -7,143 +7,65 @@
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <asm_defs.h>
|
||||
|
||||
FUNCTION(__x86_setup_system_time):
|
||||
ret
|
||||
FUNCTION_END(__x86_setup_system_time)
|
||||
|
||||
// TODO: Implement these.
|
||||
|
||||
/* int64 system_time(); */
|
||||
FUNCTION(system_time):
|
||||
ud2a
|
||||
ret
|
||||
FUNCTION_END(system_time)
|
||||
|
||||
|
||||
/* int64 system_time_nsecs(); */
|
||||
FUNCTION(system_time_nsecs):
|
||||
ud2a
|
||||
ret
|
||||
FUNCTION_END(system_time_nsecs)
|
||||
|
||||
#if 0
|
||||
/* saves the conversion factor needed for system_time */
|
||||
.lcomm cv_factor 4
|
||||
.lcomm cv_factor_nsecs 4
|
||||
.lcomm cv_factor_nsecs_shift 1
|
||||
.lcomm cv_factor 8
|
||||
.lcomm cv_factor_nsecs 8
|
||||
|
||||
|
||||
.text
|
||||
|
||||
|
||||
FUNCTION(__x86_setup_system_time):
|
||||
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
|
||||
movq %rdi, cv_factor
|
||||
movq %rsi, cv_factor_nsecs
|
||||
ret
|
||||
FUNCTION_END(__x86_setup_system_time)
|
||||
|
||||
|
||||
/* int64 system_time(); */
|
||||
FUNCTION(system_time):
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
movl cv_factor, %ebx
|
||||
movq cv_factor, %rcx
|
||||
|
||||
/* load 64-bit factor into %eax (low), %edx (high) */
|
||||
rdtsc /* time in %edx,%eax */
|
||||
// Load 64-bit TSC into %eax (low), %edx (high).
|
||||
rdtsc
|
||||
|
||||
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
|
||||
// Convert into a single 64-bit value.
|
||||
shl $32, %rdx
|
||||
orq %rdx, %rax
|
||||
|
||||
// Multiply by conversion factor, result in %rax (low), %rdx (high).
|
||||
mulq %rcx
|
||||
|
||||
// Shift the result right by 32 bits.
|
||||
shr $32, %rax
|
||||
shl $32, %rdx
|
||||
orq %rdx, %rax
|
||||
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.
|
||||
movq cv_factor_nsecs, %rcx
|
||||
|
||||
/* same algorithm as system_time(), just with a different factor */
|
||||
// Load 64-bit TSC into %eax (low), %edx (high).
|
||||
rdtsc
|
||||
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
movl cv_factor_nsecs, %ebx
|
||||
// Convert into a single 64-bit value.
|
||||
shl $32, %rdx
|
||||
orq %rdx, %rax
|
||||
|
||||
/* load 64-bit factor into %eax (low), %edx (high) */
|
||||
rdtsc /* time in %edx,%eax */
|
||||
// Multiply by conversion factor, result in %rax (low), %rdx (high).
|
||||
mulq %rcx
|
||||
|
||||
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
|
||||
// Shift the result right by 32 bits.
|
||||
shr $32, %rax
|
||||
shl $32, %rdx
|
||||
orq %rdx, %rax
|
||||
ret
|
||||
FUNCTION_END(system_time_nsecs)
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user