Automagic SYSCTLs

Bruce Evans brde at optusnet.com.au
Sat Jan 22 02:18:53 UTC 2011


On Fri, 21 Jan 2011, John Baldwin wrote:

> On Friday, January 21, 2011 12:04:28 pm mdf at freebsd.org wrote:
>> Bruce suggested an alternate mechanism, which is to use the size the
>> app passed in if the data will fit, and ENOMEM otherwise.  This would
>> in theory affect the ABI but in practice shouldn't do much, except
>> that today sysctl_handle_long() will truncate the data for a 32-bit
>> app and my intended new code would only SYSCTL_OUT to a 4-byte
>> user-space variable when the data fits without loss of information.
>
> I think your approach is better since 64-bit stat counters may overflow and
> I'd rather get an overflowed counter in my 32-bit app in that case than no
> counter at all, esp. since the 32-bit app may know that the counter can wrap
> and handle wrapping internally.
>
>> The answer is further complicated by the difference between sysctl(8)
>> and sysctl(3).  sysctl(8) can essentially be made well-behaved, but
>> it's not clear what people may be doing with sysctl(3).  However, it
>> is true that, at the moment, it requires a lot of work to push out an
>> array of longs that are 4/8 bytes on 64-bit kernel depending only on
>> the bitness of the app, without a specialized handler in the kernel.
>
> The array of longs was my initial main worry, but sysctl_handle_long() doesn't
> actually handle arrays, it only handles a single long.  Anything that uses an
> array of longs (such as cp_time[]) has to use a SYSCTL_PROC() handler and that
> will just have to use the SCTL_32 flag (or whatever it is called) just like it
> does now to handle 32-bit compat.

cp_time?  This shows how messy things are.  With stathz = 128, it overflows
after only 194 days on 32-bit systems.  Its type is bogusly long[], so
overflows causes undefined behaviour.  OTOH, the overflow is benign on
2's complement machines, and 32-bit applications always had to deal with it. 
They should pretend it is unsigned long and mostly take differences of it,
so it mostly works even after it wraps on after only 388 days.  But 388 days
is is enough for someones, so I guess most applications ignore the
possibilities of overflows and wraps.  There are many other counters that
stop working properly after some time, but some use honest u_int's so they
only wrap and wrap at the same point for 64-bit systems and aren't so hard
to export.  The sysctl cp_time handlers have a messy specialized handler
to convert from longs to unsigned ints (should be from longs to int32_t's,
but there is no difference if longs are 2's complement of the uptime is
less than 194 days).  This conversion can be done in an unspecialized
way, at least for small arrays where you can allocate buffers on the
stack like the cp_time handlers do.

Other cases might be even messier.  Anyway, failing when a value in
the array cannot be represented in 32 bits is not the right error
handling.  The kernel itself allows the values of most statistics
counters to blindly overflow.  When the kernel is fixed to fail on
overflow, the sysctls should fail too :-).  BTW, gmon(3) shuts down
the whole profiling when a single counter overflows (after settting
the overflowed value from 0 back to 0xFFFF, and my low-resolution
kernel profiling does this too).  After enough failures, someone might
fix the counter sizes to work in 2011 as well as they did in 1981.

Bruce


More information about the freebsd-arch mailing list