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
This commit is contained in:
@@ -105,7 +105,7 @@ extern void reset_dbats(void);
|
|||||||
//extern void setl2cr(unsigned int val);
|
//extern void setl2cr(unsigned int val);
|
||||||
extern long long get_time_base(void);
|
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
|
// defined in libroot: os/arch/system_time.c
|
||||||
int64 __ppc_get_time_base(void);
|
int64 __ppc_get_time_base(void);
|
||||||
// defined in libroot: os/arch/system_time_asm.S
|
// defined in libroot: os/arch/system_time_asm.S
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ struct ppc_real_time_data {
|
|||||||
|
|
||||||
struct arch_real_time_data {
|
struct arch_real_time_data {
|
||||||
struct ppc_real_time_data data[2];
|
struct ppc_real_time_data data[2];
|
||||||
vint64 system_time_conversion_factor;
|
vint32 system_time_conversion_factor;
|
||||||
vint32 version;
|
vint32 version;
|
||||||
// Since there're no cheap atomic_{set,get,add}64() on PPC 32 (i.e. one
|
// 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
|
// that doesn't involve a syscall), we can't have just a single
|
||||||
|
|||||||
@@ -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
|
// init the arch specific part of the real_time_data
|
||||||
data->arch_data.data[0].system_time_offset = 0;
|
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
|
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;
|
data->arch_data.version = 0;
|
||||||
|
|
||||||
// init spinlock
|
// init spinlock
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
#include <real_time_data.h>
|
#include <real_time_data.h>
|
||||||
|
|
||||||
|
|
||||||
static vint64 *sConversionFactor;
|
static vint32 *sConversionFactor;
|
||||||
|
|
||||||
void
|
void
|
||||||
__ppc_setup_system_time(vint64 *cvFactor)
|
__ppc_setup_system_time(vint32 *cvFactor)
|
||||||
{
|
{
|
||||||
sConversionFactor = cvFactor;
|
sConversionFactor = cvFactor;
|
||||||
}
|
}
|
||||||
@@ -26,13 +26,7 @@ bigtime_t
|
|||||||
system_time(void)
|
system_time(void)
|
||||||
{
|
{
|
||||||
uint64 timeBase = __ppc_get_time_base();
|
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
|
uint32 cv = *sConversionFactor;
|
||||||
// about 2^(64 - 20). This might sound a lot, but the conversion factor
|
return (timeBase >> 32) * cv + (((timeBase & 0xffffffff) * cv) >> 32);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user