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
>  
>  
>

Reply via email to