9.1 callout behavior

Adrian Chadd adrian at freebsd.org
Wed Sep 17 00:53:54 UTC 2014


On 16 September 2014 17:38, Adrian Chadd <adrian at freebsd.org> wrote:
> So, it did show up even if I say to run the callout on cpu #0 - any
> kind of load on that CPU and that callwheel still gets run on another
> CPU.
>
> What I next did was compile up KTR:
>
> include GENERIC
> ident TESTING
> options KTR
> options ALQ
> options KTR_ALQ
> options KTR_COMPILE=0xffffffff
>
> .. then enable KTR_CALLOUT, and I see:
>
>   4175   0  884780740167480 precision set for 0xffffffff818194f8: 0.01999997
>   4174   0  884780667893634 callout lock 0xffffffff818194f8 func
> 0xffffffff818191d0 arg 0xffffffff818194f8
>   4149   0  884780455441940 callout 0xffffffff818194f8 finished
>   4148   0  884780455441414 scheduled 0xffffffff818194f8 func
> 0xffffffff818191d0 arg 0xffffffff818194f8 in 561.4a5c984a
>   4147   0  884780455440600 precision set for 0xffffffff818194f8: 0.01999997
>   4132   0  884780373374060 callout lock 0xffffffff818194f8 func
> 0xffffffff818191d0 arg 0xffffffff818194f8
>   4103   0  884780170731868 callout 0xffffffff818194f8 finished
>   4102   0  884780170731468 scheduled 0xffffffff818194f8 func
> 0xffffffff818191d0 arg 0xffffffff818194f8 in 561.25c0f291
>   4101   0  884780170730948 precision set for 0xffffffff818194f8: 0.01999997
>   4086   0  884780089391348 callout lock 0xffffffff818194f8 func
> 0xffffffff818191d0 arg 0xffffffff818194f8
>   4058   0  884779886019688 callout 0xffffffff818194f8 finished
>
> .. and those 561.xxxx values are sbintime values.
>
> The delta looks like it's ~ 142mS, which is in line with what your
> callout routine reports. So the math to calculate the "next" event is
> bumping it along to that value instead of 100mS.
>
> I'm going to update one of these boxes to -HEAD and see if it's still
> a problem there.

So the test case uses callout_reset(), which is the "older" way of doing it.

What callout_reset() does is:

* convert to sbintime_t;
* set the callout precision to 0;
* set C_HARDCLOCK.

Now, C_HARDCLOCK doesn't read the last clock - it reads the last
per-cpu clock value. I have no idea if PCPU_GET(hardclocktime) is
_actually_ going to be equal across all CPUs - and boy if it isn't I'm
not going to fix it - but the point here is it's not going to be
updated very often when the system is idle and not receiving many
interrupts.

When I change the code to use callout_reset_sbt():

    callout_reset_sbt(&cp->co, (SBT_1S * 100) / 1000, 0,
ticktock_callback, cp, 0);

.. and

    callout_reset_sbt(&c.co, (SBT_1S * 100) / 1000, 0,
ticktock_callback, &c, 0);

To fire at the same interval that you did (hz / 10; so 100mS) then it
worked out perfectly fine.



-a


More information about the freebsd-hackers mailing list