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:
@@ -367,9 +367,14 @@ extern "C" {
|
|||||||
|
|
||||||
struct arch_thread;
|
struct arch_thread;
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
void __x86_setup_system_time(uint64 conversionFactor,
|
||||||
|
uint64 conversionFactorNsecs);
|
||||||
|
#else
|
||||||
void __x86_setup_system_time(uint32 conversionFactor,
|
void __x86_setup_system_time(uint32 conversionFactor,
|
||||||
uint32 conversionFactorNsecs, bool conversionFactorNsecsShift);
|
uint32 conversionFactorNsecs, bool conversionFactorNsecsShift);
|
||||||
|
#endif
|
||||||
|
|
||||||
void x86_context_switch(struct arch_thread* oldState,
|
void x86_context_switch(struct arch_thread* oldState,
|
||||||
struct arch_thread* newState);
|
struct arch_thread* newState);
|
||||||
void x86_userspace_thread_exit(void);
|
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;
|
uint32 conversionFactor = args->arch_args.system_time_cv_factor;
|
||||||
uint64 conversionFactorNsecs = (uint64)conversionFactor * 1000;
|
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) {
|
if (conversionFactorNsecs >> 32 != 0) {
|
||||||
// the TSC frequency is < 1 GHz, which forces us to shift the factor
|
// the TSC frequency is < 1 GHz, which forces us to shift the factor
|
||||||
__x86_setup_system_time(conversionFactor, conversionFactorNsecs >> 16,
|
__x86_setup_system_time(conversionFactor, conversionFactorNsecs >> 16,
|
||||||
@@ -828,6 +834,7 @@ arch_cpu_init(kernel_args* args)
|
|||||||
// the TSC frequency is >= 1 GHz
|
// the TSC frequency is >= 1 GHz
|
||||||
__x86_setup_system_time(conversionFactor, conversionFactorNsecs, false);
|
__x86_setup_system_time(conversionFactor, conversionFactorNsecs, false);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,143 +7,65 @@
|
|||||||
* Distributed under the terms of the NewOS License.
|
* Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <asm_defs.h>
|
#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 */
|
/* saves the conversion factor needed for system_time */
|
||||||
.lcomm cv_factor 4
|
.lcomm cv_factor 8
|
||||||
.lcomm cv_factor_nsecs 4
|
.lcomm cv_factor_nsecs 8
|
||||||
.lcomm cv_factor_nsecs_shift 1
|
|
||||||
|
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
|
|
||||||
FUNCTION(__x86_setup_system_time):
|
FUNCTION(__x86_setup_system_time):
|
||||||
movl 4(%esp), %eax
|
movq %rdi, cv_factor
|
||||||
movl %eax, cv_factor
|
movq %rsi, cv_factor_nsecs
|
||||||
movl 8(%esp), %eax
|
|
||||||
movl %eax, cv_factor_nsecs
|
|
||||||
movb 12(%esp), %al
|
|
||||||
movb %al, cv_factor_nsecs_shift
|
|
||||||
ret
|
ret
|
||||||
FUNCTION_END(__x86_setup_system_time)
|
FUNCTION_END(__x86_setup_system_time)
|
||||||
|
|
||||||
|
|
||||||
/* int64 system_time(); */
|
/* int64 system_time(); */
|
||||||
FUNCTION(system_time):
|
FUNCTION(system_time):
|
||||||
pushl %ebx
|
movq cv_factor, %rcx
|
||||||
pushl %ecx
|
|
||||||
movl cv_factor, %ebx
|
|
||||||
|
|
||||||
/* load 64-bit factor into %eax (low), %edx (high) */
|
// Load 64-bit TSC into %eax (low), %edx (high).
|
||||||
rdtsc /* time in %edx,%eax */
|
rdtsc
|
||||||
|
|
||||||
movl %edx, %ecx /* save high half */
|
// Convert into a single 64-bit value.
|
||||||
mull %ebx /* truncate %eax, but keep %edx */
|
shl $32, %rdx
|
||||||
movl %ecx, %eax
|
orq %rdx, %rax
|
||||||
movl %edx, %ecx /* save high half of low */
|
|
||||||
mull %ebx /*, %eax*/
|
// Multiply by conversion factor, result in %rax (low), %rdx (high).
|
||||||
/* now compute [%edx, %eax] + [%ecx], propagating carry */
|
mulq %rcx
|
||||||
subl %ebx, %ebx /* need zero to propagate carry */
|
|
||||||
addl %ecx, %eax
|
// Shift the result right by 32 bits.
|
||||||
adc %ebx, %edx
|
shr $32, %rax
|
||||||
popl %ecx
|
shl $32, %rdx
|
||||||
popl %ebx
|
orq %rdx, %rax
|
||||||
ret
|
ret
|
||||||
FUNCTION_END(system_time)
|
FUNCTION_END(system_time)
|
||||||
|
|
||||||
|
|
||||||
/* int64 system_time_nsecs(); */
|
/* int64 system_time_nsecs(); */
|
||||||
FUNCTION(system_time_nsecs):
|
FUNCTION(system_time_nsecs):
|
||||||
testb $0, cv_factor_nsecs_shift
|
// Same algorithm as system_time(), just with a different factor.
|
||||||
jne 1f
|
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
|
// Convert into a single 64-bit value.
|
||||||
pushl %ecx
|
shl $32, %rdx
|
||||||
movl cv_factor_nsecs, %ebx
|
orq %rdx, %rax
|
||||||
|
|
||||||
/* load 64-bit factor into %eax (low), %edx (high) */
|
// Multiply by conversion factor, result in %rax (low), %rdx (high).
|
||||||
rdtsc /* time in %edx,%eax */
|
mulq %rcx
|
||||||
|
|
||||||
movl %edx, %ecx /* save high half */
|
// Shift the result right by 32 bits.
|
||||||
mull %ebx /* truncate %eax, but keep %edx */
|
shr $32, %rax
|
||||||
movl %ecx, %eax
|
shl $32, %rdx
|
||||||
movl %edx, %ecx /* save high half of low */
|
orq %rdx, %rax
|
||||||
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
|
ret
|
||||||
FUNCTION_END(system_time_nsecs)
|
FUNCTION_END(system_time_nsecs)
|
||||||
#endif
|
|
||||||
|
|||||||
Reference in New Issue
Block a user