You probably want to disable it entirely so it doesn't need to execute a branch condition every time it reads the timer, ie with #ifdef. This code path would be critical for timing.
Damien Sent from Proton Mail Android -------- Original Message -------- On 23/3/25 9:13 pm, Zhaoming Luo <zhming...@163.com> wrote: > Hi, > > I'm wondering the code for checking whether a high-precision code is > available should be in mach_clock.c or in the machine-dependent > directory. In this patch it's in the machine-dependent directory. It can > ensure the backward compactability. Otherwise compiling a gnumach with > only '../configure' will cause page fault at the startup. > ``` > +uint32_t > +hpclock_read_counter(void) > +{ > + if (hpet_addr != NULL) > + return HPET32(HPET_COUNTER); > + else > + return 0; > +} > + > +uint32_t > +hpclock_get_counter_period_nsec(void) > +{ > + if (hpet_addr != NULL) > + return hpet_period_nsec; > + else > + return 0; > +} > ``` > > Zhaoming > --- > i386/i386/apic.c | 17 +++++++++++++++++ > i386/i386at/model_dep.c | 2 ++ > kern/mach_clock.c | 36 +++++++++++++++++++++++++++++++++++- > kern/mach_clock.h | 4 ++++ > 4 files changed, 58 insertions(+), 1 deletion(-) > > diff --git a/i386/i386/apic.c b/i386/i386/apic.c > index 77d555b5..6cacd5fa 100644 > --- a/i386/i386/apic.c > +++ b/i386/i386/apic.c > @@ -479,3 +479,20 @@ hpet_mdelay(uint32_t ms) > hpet_udelay(ms * 1000); > } > > +uint32_t > +hpclock_read_counter(void) > +{ > + if (hpet_addr != NULL) > + return HPET32(HPET_COUNTER); > + else > + return 0; > +} > + > +uint32_t > +hpclock_get_counter_period_nsec(void) > +{ > + if (hpet_addr != NULL) > + return hpet_period_nsec; > + else > + return 0; > +} > diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c > index 30449c37..42dadeb8 100644 > --- a/i386/i386at/model_dep.c > +++ b/i386/i386at/model_dep.c > @@ -223,7 +223,9 @@ void machine_init(void) > */ > gdt_descr_tmp.linear_base += apboot_addr; > apboot_jmp_offset += apboot_addr; > +#endif > > +#ifdef APIC > /* > * Initialize the HPET > */ > diff --git a/kern/mach_clock.c b/kern/mach_clock.c > index 5501b7b8..9bae3439 100644 > --- a/kern/mach_clock.c > +++ b/kern/mach_clock.c > @@ -83,6 +83,15 @@ unsigned tickadj = 500 / HZ; /* can adjust 100 usecs > per second */ > unsigned bigadj = 1000000; /* adjust 10*tickadj if adjustment > > bigadj */ > > +/* A high-precision (hardware) clock is taken into account to increase the > + * accuracy of the functions used for getting time (e.g. host_get_time64()). > + * The counter of the clock is read once in every clock interrupt. When any > + * of the functions used for getting time is called, the counter is read > again > + * and the difference between these two read is multiplied by the counter > + * period and added to the read value from time or uptime to get a more > + * accurate time read. */ > +uint32_t last_hpc_read = 0; > + > /* > * This update protocol, with a check value, allows > * do { > @@ -128,7 +137,8 @@ MACRO_BEGIN > \ > __sync_synchronize(); \ > (time)->nanoseconds = mtime->time_value.nanoseconds; \ > __sync_synchronize(); \ > - } while ((time)->seconds != mtime->check_seconds64); \ > + } while ((time)->seconds != mtime->check_seconds64); \ > + time_value64_add_hpc(time); \ > MACRO_END > > #define read_mapped_uptime(uptime) \ > @@ -139,6 +149,7 @@ MACRO_BEGIN > \ > (uptime)->nanoseconds = mtime->uptime_value.nanoseconds;\ > __sync_synchronize(); \ > } while ((uptime)->seconds != mtime->check_upseconds64); \ > + time_value64_add_hpc(uptime); \ > MACRO_END > > def_simple_lock_irq_data(static, timer_lock) /* lock for ... */ > @@ -292,6 +303,7 @@ void clock_interrupt( > } > } > } > + last_hpc_read = hpclock_read_counter(); > } > > /* > @@ -426,6 +438,28 @@ clock_boottime_update(const struct time_value64 > *new_time) > time_value64_add(&clock_boottime_offset, &delta); > } > > +/* > + * Add the time value since last clock interrupt in nanosecond. > + */ > +static void > +time_value64_add_hpc(time_value64_t *value) > +{ > + uint32_t now = hpclock_read_counter(); > + /* Time since last clock interrupt in nanosecond. */ > + int64_t ns = (now - last_hpc_read) * hpclock_get_counter_period_nsec(); > + > + /* Limit the value of ns under the period of a clock interrupt in case > + imprecise computation causes ns greater than the clock interrupt > + period. */ > + if (ns > tick * 1000) > + /* Let ns stuck at the end of the clock interrupt period when > + something bad happens. */ > + ns = (tick * 1000) - 1; > + > + time_value64_add_nanos(value, ns); > +} > + > + > /* > * Record a timestamp in STAMP. Records values in the boot-time clock > * frame. > diff --git a/kern/mach_clock.h b/kern/mach_clock.h > index d4f04f5e..e83b638c 100644 > --- a/kern/mach_clock.h > +++ b/kern/mach_clock.h > @@ -110,4 +110,8 @@ extern boolean_t untimeout(timer_func_t *fcn, const void > *param); > extern int timeopen(dev_t dev, int flag, io_req_t ior); > extern void timeclose(dev_t dev, int flag); > > +/* For high-precision clocks. */ > +extern uint32_t hpclock_read_counter(void); > +extern uint32_t hpclock_get_counter_period_nsec(void); > + > #endif /* _KERN_MACH_CLOCK_H_ */ > -- > 2.47.2 > > >