I wonder if the divergence between the kernel and userland
implementations might become a source of problems later. For sensor
data, wouldn't it be easier to simply change the units? (This is what
I've done in situations like this -- examples are battery voltages --
express the result in mV or uV instead of V.) That way consumers can be
either in the kernel or userland -- especially if at some point in the
future you wind up having a kernel entity that wants to participate in
this stuff. Similar in 802.11, express frequencies as Hz instead of
MHz, etc.
Consider all this a weak objection, with a possible recommendation to
look for alternatives. If there are compelling reasons why just
changing the units won't work, then I've no objection.
-- Garrett
Cynthia McGuire wrote:
> Template Version: @(#)sac_nextcase 1.66 04/17/08 SMI
> This information is Copyright 2008 Sun Microsystems
> 1. Introduction
> 1.1. Project/Component Working Name:
> Extending libnvpair for type double
> 1.2. Name of Document Author/Supplier:
> Author: Robert Johnston
> 1.3 Date of This Document:
> 08 July, 2008
> 4. Technical Description
>
> The key components of Solaris FMA (e.g.the fault manager and libtopo)
> maintain their property and state information using libnvpair. As part of the
> work to develop a sensor abstraction layer for FMA, we require the ability
> to represent analog sensor readings, which are typically expressed as
> floating point values. Therefore it has become necessary to extend libnvpair
> to allow floating point values.
>
> This case seeks to extend libnvpair with three new interfaces to
> <libnvpair.h>:
>
> int nvlist_add_double(nvlist_t *nvl, const char *name, double val);
> int nvlist_lookup_double(nvlist_t *nvl , const char *name, double *);
> int nvpair_value_double(nvpair_t *nvpair, double *val);
>
> Because use of floating point types is discouraged in the kernel, and all of
> the FMA components that will be consuming these new interfaces live in
> userland, they will be made available via libnvpair but not in the kernel DDI.
> Preprocessor guards will be used to ensure the new code is not compiled
> into the kernel.
>
> The libnvpair(3LIB) man page will be updated to include the new functions.
>
> The man pages for the nvlist_add/lookup_* and nvpair_value_* functions all
> link to one of the following three man pages, respectively, which
> includes content that covers the various forms of the interfaces for all
> of the different data types:
>
> nvlist_add_boolean(3NVPAIR)
> nvlist_lookup_boolean(3NVPAIR)
> nvpair_value_byte(3NVPAIR)
>
> These three man pages will be updated to include the new interfaces for
> DATA_TYPE_DOUBLE. The updated man page conent is included below.
>
>
> Name-value Pair Library Functions nvlist_add_boolean(3NVPAIR)
>
> NAME
> nvlist_add_boolean, nvlist_add_boolean_value,
> nvlist_add_byte, nvlist_add_int8, nvlist_add_uint8,
> nvlist_add_int16, nvlist_add_uint16, nvlist_add_int32,
> nvlist_add_uint32, nvlist_add_int64, nvlist_add_uint64,
> nvlist_add_double, nvlist_add_string, nvlist_add_nvlist,
> nvlist_add_nvpair, nvlist_add_boolean_array,
> nvlist_add_byte_array, nvlist_add_int8_array,
> nvlist_add_uint8_array, nvlist_add_int16_array,
> nvlist_add_uint16_array, nvlist_add_int32_array,
> nvlist_add_uint32_array, nvlist_add_int64_array,
> nvlist_add_uint64_array, nvlist_add_string_array,
> nvlist_add_nvlist_array - add new name-value pair to nvlist_t
>
> SYNOPSIS
> cc [ flag... ] file... -lnvpair [ library... ]
> #include <libnvpair.h>
>
> int nvlist_add_boolean(nvlist_t *nvl, const char *name);
>
> int nvlist_add_boolean_value(nvlist_t *nvl,
> const char *name, boolean_t val);
>
> int nvlist_add_byte(nvlist_t *nvl, const char *name,
> uchar_t val);
>
> int nvlist_add_int8(nvlist_t *nvl, const char *name,
> int8_t val);
>
> int nvlist_add_uint8(nvlist_t *nvl, const char *name,
> uint8_t val);
>
> int nvlist_add_int16(nvlist_t *nvl, const char *name,
> int16_t val);
>
> int nvlist_add_uint16(nvlist_t *nvl, const char *name,
> uint16_t val);
>
> int nvlist_add_int32(nvlist_t *nvl, const char *name,
> int32_t val);
>
> int nvlist_add_uint32(nvlist_t *nvl, const char *name,
> uint32_t val);
>
> int nvlist_add_int64(nvlist_t *nvl, const char *name,
> int64_t val);
>
> int nvlist_add_uint64(nvlist_t *nvl, const char *name,
> uint64_t val);
>
> int nvlist_add_double(nvlist_t *nvl, const char *name,
> double val);
>
> int nvlist_add_string(nvlist_t *nvl, const char *name,
> const char *val);
>
> int nvlist_add_nvlist(nvlist_t *nvl, const char *name,
> nvlist_t *val);
>
> int nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp);
>
> int nvlist_add_boolean_array(nvlist_t *nvl, const char *name,
> boolean_t *val, uint_t nelem);
>
> int nvlist_add_byte_array(nvlist_t *nvl, const char *name,
> uchar_t *val, uint_t nelem);
>
> int nvlist_add_int8_array(nvlist_t *nvl, const char *name,
> int8_t *val, uint_t nelem);
>
> int nvlist_add_uint8_array(nvlist_t *nvl, const char *name,
> uint8_t *val, uint_t nelem);
>
> int nvlist_add_int16_array(nvlist_t *nvl, const char *name,
> int16_t *val, uint_t nelem);
>
> int nvlist_add_uint16_array(nvlist_t *nvl, const char *name,
> uint16_t *val, uint_t nelem);
>
> int nvlist_add_int32_array(nvlist_t *nvl, const char *name,
> int32_t *val, uint_t nelem);
>
> int nvlist_add_uint32_array(nvlist_t *nvl, const char *name,
> uint32_t *val, uint_t nelem);
>
> int nvlist_add_int64_array(nvlist_t *nvl, const char *name,
> int64_t *val, uint_t nelem);
>
> int nvlist_add_uint64_array(nvlist_t *nvl, const char *name,
> uint64_t *val, uint_t nelem);
>
> int nvlist_add_string_array(nvlist_t *nvl, const char *name,
> char *const *val, uint_t nelem);
>
> int nvlist_add_nvlist_array(nvlist_t *nvl, const char *name,
> nvlist_t **val, uint_t nelem);
>
> PARAMETERS
> nvl The nvlist_t (name-value pair list) to be pro-
> cessed.
>
> nvp The nvpair_t (name-value pair) to be processed.
>
> name Name of the nvpair (name-value pair).
>
> nelem Number of elements in value (that is, array size).
>
> val Value or starting address of the array value.
>
> DESCRIPTION
> These functions add a new name-value pair to an nvlist_t.
> The uniqueness of nvpair name and data types follows the
> nvflag argument specified for nvlist_alloc(). See
> nvlist_alloc(3NVPAIR).
>
> If NV_UNIQUE_NAME was specified for nvflag, existing nvpairs
> with matching names are removed before the new nvpair is
> added.
>
> If NV_UNIQUE_NAME_TYPE was specified for nvflag, existing
> nvpairs with matching names and data types are removed
> before the new nvpair is added.
>
> If neither was specified for nvflag, the new nvpair is
> unconditionally added at the end of the list. The library
> preserves the order of the name-value pairs across packing,
> unpacking, and duplication.
>
> Multiple threads can simultaneously read the same nvlist_t,
> but only one thread can actively change a given nvlist_t at
> a time. The caller is responsible for the synchronization.
>
> The nvlist_add_boolean() function is deprecated. The
> nvlist_add_boolean_value() function should be used instead.
>
> RETURN VALUES
> These functions return 0 on success and an error value on
> failure.
>
> ERRORS
> These functions will fail if:
>
> EINVAL There is an invalid argument.
>
> ENOMEM There is insufficient memory.
>
> ATTRIBUTES
> See attributes(5) for descriptions of the following attri-
> butes:
>
> ____________________________________________________________
> | ATTRIBUTE TYPE | ATTRIBUTE VALUE |
> |____________________________|______________________________|
> | Interface Stability | Evolving |
> |____________________________|______________________________|
> | MT-Level | MT-Safe |
> |____________________________|______________________________|
>
> SEE ALSO
> libnvpair(3LIB), attributes(5)
>
>
>
> Name-value Pair Library Functions nvlist_lookup_boolean(3NVPAIR)
>
> NAME
> nvlist_lookup_boolean, nvlist_lookup_boolean_value,
> nvlist_lookup_byte, nvlist_lookup_int8, nvlist_lookup_uint8,
> nvlist_lookup_int16, nvlist_lookup_uint16,
> nvlist_lookup_int32, nvlist_lookup_uint32,
> nvlist_lookup_int64, nvlist_lookup_uint64,
> nvlist_lookup_double, nvlist_lookup_string,
> nvlist_lookup_nvlist, nvlist_lookup_boolean_array,
> nvlist_lookup_byte_array, nvlist_lookup_int8_array,
> nvlist_lookup_uint8_array, nvlist_lookup_int16_array,
> nvlist_lookup_uint16_array, nvlist_lookup_int32_array,
> nvlist_lookup_uint32_array, nvlist_lookup_int64_array,
> nvlist_lookup_uint64_array, nvlist_lookup_nvlist_array,
> nvlist_lookup_string_array,
> nvlist_lookup_pairs - match name and type indicated by the
> interface name and retrieve data value
>
> SYNOPSIS
> cc [ flag... ] file... -lnvpair [ library... ]
> #include <libnvpair.h>
>
> int nvlist_lookup_boolean(nvlist_t *nvl, const char *name);
>
> int nvlist_lookup_boolean_value(nvlist_t *nvl,
> const char *name, boolean_t *val);
>
> int nvlist_lookup_byte(nvlist_t *nvl, const char *name,
> uchar_t *val);
>
> int nvlist_lookup_int8(nvlist_t *nvl, const char *name,
> int8_t *val);
>
> int nvlist_lookup_uint8(nvlist_t *nvl, const char *name,
> uint8_t *val);
>
> int nvlist_lookup_int16(nvlist_t *nvl, const char *name,
> int16_t *val);
>
> int nvlist_lookup_uint16(nvlist_t *nvl, const char *name,
> uint16_t *val);
>
> int nvlist_lookup_int32(nvlist_t *nvl, const char *name,
> int32_t *val);
>
> int nvlist_lookup_uint32(nvlist_t *nvl, const char *name,
> uint32_t *val);
>
> int nvlist_lookup_int64(nvlist_t *nvl, const char *name,
> int64_t *val);
>
> int nvlist_lookup_uint64(nvlist_t *nvl, const char *name,
> uint64_t *val);
>
> int nvlist_lookup_double(nvlist_t *nvl , const char *name,
> double *);
>
> int nvlist_lookup_string(nvlist_t *nvl, const char *name,
> char **val);
>
> int nvlist_lookup_nvlist(nvlist_t *nvl, const char *name,
> nvlist_t **val);
>
> int nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name,
> boolean_t **val, uint_t *nelem);
>
> int nvlist_lookup_byte_array(nvlist_t *nvl, const char *name,
> uchar_t **val, uint_t *nelem);
>
> int nvlist_lookup_int8_array(nvlist_t *nvl, const char *name,
> int8_t **val, uint_t *nelem);
>
> int nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name,
> uint8_t **val, uint_t *nelem);
>
> int nvlist_lookup_int16_array(nvlist_t *nvl, const char *name,
> int16_t **val, uint_t *nelem);
>
> int nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name,
> uint16_t **val, uint_t *nelem);
>
> int nvlist_lookup_int32_array(nvlist_t *nvl, const char *name,
> int32_t **val, uint_t *nelem);
>
> int nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name,
> uint32_t **val, uint_t *nelem);
>
> int nvlist_lookup_int64_array(nvlist_t *nvl, const char *name,
> int64_t **val, uint_t *nelem);
>
> int nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name,
> uint64_t **val, uint_t *nelem);
>
> int nvlist_lookup_string_array(nvlist_t *nvl, const char *name,
> char ***val, uint_t *nelem);
>
> int nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name,
> nvlist_t ***val, uint_t *nelem);
>
> int nvlist_lookup_pairs(nvlist_t *nvl, int flag...);
>
> PARAMETERS
> nvl The nvlist_t to be processed.
>
> name Name of the name-value pair to search.
>
> nelem Address to store the number of elements in value.
>
> val Address to store the starting address of the value.
>
> flag Specify bit fields defining lookup behavior:
>
> NV_FLAG_NOENTOK The retrival function will not
> fail if no matching name-value
> pair is found.
>
> DESCRIPTION
> These functions find the nvpair (name-value pair) that
> matches the name and type as indicated by the interface
> name. If one is found, nelem and val are modified to contain
> the number of elements in value and the starting address of
> data, respectively.
>
> These functions work for nvlists (lists of name-value pairs)
> allocated with NV_UNIQUE_NAME or NV_UNIQUE_NAME_TYPE speci-
> fied in nvlist_alloc(). (See nvlist_alloc(3NVPAIR).) If this
> is not the case, the function returns ENOTSUP because the
> list potentially contains multiple nvpairs with the same
> name and type.
>
> Multiple threads can simultaneously read the same nvlist_t
> but only one thread can actively change a given nvlist_t at
> a time. The caller is responsible for the synchronization.
>
> All memory required for storing the array elements, includ-
> ing string value, are managed by the library. References to
> such data remain valid until nvlist_free() is called on nvl.
>
> The nvlist_lookup_pairs() function retrieves a set of
> nvpairs. The arguments are a null-terminated list of pairs
> (data type DATA_TYPE_BOOLEAN), triples (non-array data
> types) or quads (array data types). The interpretation of
> the arguments depends on the value of type (see
> nvpair_type(3NVPAIR)) as follows:
>
> name Name of the name-value pair to search.
>
> type Data type (see nvpair_type(3NVPAIR)).
>
> val Address to store the starting address of the value.
> When using data type DATA_TYPE_BOOLEAN, the val
> argument is omitted.
>
> nelem Address to store the number of elements in value.
> Non-array data types have only one argument and
> nelem is omitted.
>
> The order of the arguments is name, type, [val], [nelem].
>
> When using NV_FLAG_NOENTOK and no matching name-value pair
> is found, the memory pointed to by val and nelem is left
> untouched.
>
> RETURN VALUES
> These functions return 0 on success and an error value on
> failure.
>
> ERRORS
> These functions will fail if:
>
> EINVAL There is an invalid argument.
>
> ENOENT No matching name-value pair is found
>
> ENOTSUP An encode/decode method is not supported.
>
> ATTRIBUTES
> See attributes(5) for descriptions of the following attri-
> butes:
>
> ____________________________________________________________
> | ATTRIBUTE TYPE | ATTRIBUTE VALUE |
> |____________________________|______________________________|
> | Interface Stability | Evolving |
> |____________________________|______________________________|
> | MT-Level | MT-Safe |
> |____________________________|______________________________|
>
> SEE ALSO
> libnvpair(3LIB), nvpair_type(3NVPAIR), attributes(5)
>
>
> Name-value Pair Library Functions nvpair_value_byte(3NVPAIR)
>
> NAME
> nvpair_value_byte, nvpair_value_boolean_value,
> nvpair_value_int8, nvpair_value_uint8, nvpair_value_int16,
> nvpair_value_uint16, nvpair_value_int32,
> nvpair_value_uint32, nvpair_value_int64,
> nvpair_value_uint64, nvpair_value_double,
> nvpair_value_string, nvpair_value_nvlist,
> nvpair_value_boolean_array, nvpair_value_byte_array,
> nvpair_value_int8_array, nvpair_value_uint8_array,
> nvpair_value_int16_array, nvpair_value_uint16_array,
> nvpair_value_int32_array, nvpair_value_uint32_array,
> nvpair_value_int64_array, nvpair_value_uint64_array,
> nvpair_value_string_array,
> nvpair_value_nvlist_array - retrieve value from a name-value
> pair
>
> SYNOPSIS
> cc [ flag... ] file... -lnvpair [ library... ]
> #include <libnvpair.h>
>
> int nvpair_value_byte(nvpair_t *nvpair, uchar_t *val);
>
> int nvpair_value_boolean_value(nvpair_t *nvpair,
> boolean_t *val);
>
> int nvpair_value_int8(nvpair_t *nvpair, int8_t *val);
>
> int nvpair_value_uint8(nvpair_t *nvpair, uint8_t *val);
>
> int nvpair_value_int16(nvpair_t *nvpair, int16_t *val);
>
> int nvpair_value_uint16(nvpair_t *nvpair, uint16_t *val);
>
> int nvpair_value_int32(nvpair_t *nvpair, int32_t *val);
>
> int nvpair_value_uint32(nvpair_t *nvpair, uint32_t *val);
>
> int nvpair_value_int64(nvpair_t *nvpair, int64_t *val);
>
> int nvpair_value_uint64(nvpair_t *nvpair, uint64_t *val);
>
> int nvpair_value_double(nvpair_t *nvpair, double *val);
>
> int nvpair_value_string(nvpair_t *nvpair, char **val);
>
> int nvpair_value_nvlist(nvpair_t *nvpair, nvlist_t **val);
>
> int nvpair_value_boolean_array(nvpair_t *nvpair,
> boolean_t **val, uint_t *nelem);
>
> int nvpair_value_byte_array(nvpair_t *nvpair, uchar_t **val,
> uint_t *nelem);
>
> int nvpair_value_int8_array(nvpair_t *nvpair, int8_t **val,
> uint_t *nelem);
>
> int nvpair_value_uint8_array(nvpair_t *nvpair, uint8_t **val,
> uint_t *nelem);
>
> int nvpair_value_int16_array(nvpair_t *nvpair, int16_t **val,
> uint_t *nelem);
>
> int nvpair_value_uint16_array(nvpair_t *nvpair,
> uint16_t **val, uint_t *nelem);
>
> int nvpair_value_int32_array(nvpair_t *nvpair,
> int32_t **val, uint_t *nelem);
>
> int nvpair_value_uint32_array(nvpair_t *nvpair,
> uint32_t **val, uint_t *nelem);
>
> int nvpair_value_int64_array(nvpair_t *nvpair,
> int64_t **val, uint_t *nelem);
>
> int nvpair_value_uint64_array(nvpair_t *nvpair,
> uint64_t **val, uint_t *nelem);
>
> int nvpair_value_string_array(nvpair_t *nvpair,
> char ***val, uint_t *nelem);
>
> int nvpair_value_nvlist_array(nvpair_t *nvpair,
> nvlist_t ***val, uint_t *nelem);
>
> PARAMETERS
> nvpair Name-value pair to be processed.
>
> nelem Address to store the number of elements in value.
>
> val Address to store the value or the starting address
> of the array value.
>
> DESCRIPTION
> These functions retrieve the value of nvpair. The data type
> of nvpair must match the interface name for the call to be
> successful.
>
> There is no nvpair_value_boolean(); the existence of the
> name implies the value is true.
>
> For array data types, including string, the memory contain-
> ing the data is managed by the library and references to the
> value remains valid until nvlist_free() is called on the
> nvlist_t from which nvpair is obtained. See
> nvlist_free(3NVPAIR).
>
> The value of an nvpair may not be retrieved after the nvpair
> has been removed from or replaced in an nvlist. Replacement
> can occur during pair additions to nvlists created with
> NV_UNIQUE_NAME_TYPE and NV_UNIQUE_NAME. See
> nvlist_alloc(3NVPAIR).
>
> RETURN VALUES
> These functions return 0 on success and an error value on
> failure.
>
> ERRORS
> These functions will fail if:
>
> EINVAL Either one of the arguments is NULL or the type of
> nvpair does not match the function name.
>
> ATTRIBUTES
> See attributes(5) for descriptions of the following attri-
> butes:
>
>
> ____________________________________________________________
> | ATTRIBUTE TYPE | ATTRIBUTE VALUE |
> |____________________________|______________________________|
> | Interface Stability | Evolving |
> |____________________________|______________________________|
> | MT-Level | MT-Safe |
> |____________________________|______________________________|
>
> SEE ALSO
> libnvpair(3LIB), nvlist_alloc(3NVPAIR), attributes(5)
>
>
>
>
> These interfaces are Committed and seek patch binding.
>
> 6. Resources and Schedule
> 6.4. Steering Committee requested information
> 6.4.1. Consolidation C-team Name:
> ON
> 6.5. ARC review type: FastTrack
> 6.6. ARC Exposure: open
>
>