Date: Sat, 19 Oct 2019 10:35:31 -0600 From: Ian Lepore <ian@freebsd.org> To: Milan Obuch <freebsd-hackers@dino.sk>, freebsd-hackers@freebsd.org Subject: Re: sysctl questions Message-ID: <89cc36381cd82b81b8664f701c63a96724d3f881.camel@freebsd.org> In-Reply-To: <20191019134524.3cc3d274@zeta.dino.sk> References: <20191019134524.3cc3d274@zeta.dino.sk>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?89cc36381cd82b81b8664f701c63a96724d3f881.camel>