tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: rfc: high-resolution timer framework



On Wed, Jun 25, 2008 at 03:25:40 +0000, Andrew Doran wrote:
> Hi,
Hi,

> I have some specific comments on the patch.
> 
> On Wed, Jun 25, 2008 at 04:45:50PM +0300, Alexander Shishkin wrote:
> 
>       +RB_HEAD(hrtim_tree, ptimer);
>       +RB_PROTOTYPE(hrtim_tree, ptimer, pt_rb_entry, hrtim_rb_compare);
>       +RB_GENERATE(hrtim_tree, ptimer, pt_rb_entry, hrtim_rb_compare);
> 
> The rb stuff from sys/rb.h is preferred.
Ok.

>       +/*
>       + * sys/kern/kern_hrtim.c
>       + *
>       + * High-resolution timer framework.
> 
> Usually goes after the copyright.
Ok.

>       +static inline void
>       +hrtim_signal(struct ptimer *pt, cpuid_t cpuid)
>       +static inline void
>       +_hrtim_intr_cpu(struct timeval *now, cpuid_t cpuid)  
> 
> It's unsafe to drop the lock in the middle of RBTREE_FOREACH: the tree can
> change. Also pt_proc can disappear once the lock is dropped to send a signal
> because no kind reference is held to it. I realise that the current code has
> this problem. You could, for example, wrap the entire block with proc_lock.
This one seems to be more tricky.

>       +struct hrtim_head hrtim_heads[MAXCPUS];
>       +       cpuid = curcpu()->ci_cpuid;
> 
> ci_cpuid is for MD code, cpu_index() is the MI interface. Also it's better
> to have store a pointer from struct cpu_data, and add a hrtim_cpu_attach()
> to allocate the heads dynamically.
Good point. I was looking for something like this, but must have somehow
overlooked the cpu_attach thing.

>       +struct tc_hrtim
>       +*tc_hrtim_getbest(void)
> 
> Doesn't seem to be any locking here.
Indeed.

>       +       if (pt->pt_type == CLOCK_REALTIME) {
>       +               mutex_spin_exit(&timer_lock);
>                       callout_halt(&pt->pt_ch, &timer_lock);
> 
> callout_halt() may try to drop timer_lock, but it will panic because the
> lock is unheld. 
Hm. Strange is how LOCKDEBUG never complained of such a possibility.
Will have to dig callout code.

>        int
>       +hrtimerfix(struct timeval *tv)
> 
> Why not use timespec throughout?
For historical reasons. It was never reconsidered since a while now. But
I don't see any valid reason to not use timespec instead of timeval.

>       +#ifdef LAPIC_HRTIMER
>       +void
>       +lapic_clockintr(void *arg, struct intrframe *frame)
>       +{
> 
> It breaks if the machine has more than one CPU, because clock interrupts
> will only occur on the boot CPU. Presumably it also prevents the lapic from
> being used as a timecounter source, but that's not a big deal. It's also
> unfortunate that it's optional.
Not really. Clock interrupts (and experiments confirm) nowadays occur on
all cpus, since lapic_initclocks() gets called from cpu_hatch(), which
is the final step in secondary cpus' startup code. As for the
timecounter capability, I'm not at all sure this worked as intended
before, since the accounting happens in a field of a cpu_info structure,
thus is local to current cpu and will differ between cpus.

> One solution it is to always use the i8254 for the clock interrupt, and
> trigger a broadcast IPI to the other CPUs from the i8254 clock ISR before
> calling the MI hardclock().
This could work, but I'm still in favor of a 8254-less solution to this.

>       +       { DDB_ADD_CMD("hrtim",  db_hrtim_print_cmd,     0,
>       +           "Display high-resolution timer shit.", NULL, NULL) },
> 
> s/shit/state/
Whoops. Shame on me.

Thanks for taking time and providing very valuable comments!

Regards,
--
Alex


Home | Main Index | Thread Index | Old Index