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
>
>   


Reply via email to