sysctl questions

Ian Lepore ian at freebsd.org
Sat Oct 19 16:35:39 UTC 2019


On Sat, 2019-10-19 at 13:45 +0200, Milan Obuch wrote:
> Hi,
> 
> I am working on AXI XADC driver on Zynq based Zybo Z7 board. I created
> simple PL design to be able to use this core IP. Looking in some other
> ADC driver I desided to use sysctl API to report measurements. So I did
> create mib entry in attach function like this
> 
>     snprintf(pinbuf, sizeof(inum), "%d", i);
> 
>     inpN_node = SYSCTL_ADD_NODE(ctx, inp_tree, OID_AUTO, inum,
>         CTLFLAG_RD, NULL, "ADC input");
>     inpN_tree = SYSCTL_CHILDREN(inpN_node);
> 
>     SYSCTL_ADD_PROC(ctx, inpN_tree, OID_AUTO, "read",
>         CTLFLAG_RD | CTLTYPE_UINT, &axi_xadc_inputs[i], 0,
>         axi_xadc_read_proc, "IU", "Read ADC input");
> 
> where inum is string, i is integer - input number. Top node for my
> mib entries is dev.adc.0.ain. When the above snippet is run for i from
> 0 up to Ninputs - 1, sysctl shows them in opposite order, i. e.
> 
> # sysctl dev.adc.0.ain
> dev.adc.0.ain.3.read: <some value>
> dev.adc.0.ain.2.read: <some value>
> dev.adc.0.ain.1.read: <some value>
> dev.adc.0.ain.0.read: <some value>
> 
> Why it is so? It looks for me a bit counter intuitive, I like the nodes
> be ordered the way I decide, not the other way so... so I am just
> calling the initialisation snippet for i starting with Ninput - 1 down
> to 0 and it works the way I want.
> 

The sysctl oid entries are stored in an SLIST and each new entry is
added to the head of the list, so when sysctl(8) walks the list of
children of a given oid, they get displayed in reverse order of how
they were added.

> Other thing I do not understand is my axi_xadc_read_proc is called
> *twice* per node. My procedure is short:
> 

This happens because sysctl(8) makes two calls per value retrieved. 
The first call has req->oldptr set to NULL which makes the sysctl
machinery return the length of the return value without returning the
value itself.  Sysctl(8) then allocates a buffer of the right length
and makes another call with req->oldptr pointing to the allocated
buffer to actually retrieve the value.

When there is some cost to returning the value (such as an expensive or
time-consuming hardware operation), you can check whether oldptr is
NULL or not before doing the expensive work.  For an example, see the
ads111x_sysctl_voltage() function in sys/dev/iicbus/ads111x.c

-- Ian




More information about the freebsd-hackers mailing list