Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
4.  Properties and Events Device Properties prop_op() Entry Point  Previous   Contents   Next 
   
 

Events

A system often needs to respond to an external state change in some device. For example, it may issue a warning when a component begins to overheat, or start a movie player when a DVD is inserted into a drive.

How Drivers Track Events: ddi_log_sysevent()

Device drivers use the ddi_log_sysevent(9F) interface to generate and log an event with the system; an event tells the system what has just occurred to the device. The system, in turn, queues events and passes them to the syseventd() daemon outside of kernel process space. syseventd() then passes the events on to an appropriate event-handling process, as shown in Figure 4-1.

Figure 4-1 Event Plumbing

ddi_log_sysevent() takes the following arguments:

dip

A pointer to the dev_info node for this driver.

vendor

A pointer to a string defining the driver's vendor. Third-party drivers should use their company's stock symbol or a similarly enduring identifier. Sun-supplied drivers use DDI_VENDOR_SUNW.

class

A pointer to a string defining the event's class. This is a driver-specific value. An example of a class might be a string representing a set of environmental conditions affecting a device. This value must be intelligible to the event consumer.

subclass

Also a driver-specific string, this parameter represents a subset of the class argument. For example, within a class representing environmental conditions, an event subclass might refer to the device's temperature. This value must be intelligible to the event consumer.

attr_list

A pointer to an nvlist_t structure, listing name-value attributes associated with the event. Name-value attributes, like class and subclass, are driver-defined; they refer to some specific attribute or condition of the device. For example, a device that reads both CD-ROMs and DVDs may create a string name-value pair in which the name is disc_type and the value is either cd_rom or dvd. As with class and subclass, the driver handle (outside of kernel process space) must be able to interpret name-value pairs and respond to them in an appropriate manner.

For more on name-value pairs and the nvlist_t structure, see "Event Name-Value Pairs", as well as nvlist_alloc(9F)

If there are no such attributes for an event, then this argument should be set to NULL.

eidp

The address of a sysevent_id_t structure. The sysevent_id_t structure is used to provide a unique identification for the event. ddi_log_sysevent(9F) returns this structure with a system-provided event sequence number and timestamp. See the ddi_log_sysevent(9F) page for more information on the sysevent_id_t structure.

sleep_flag

This flag indicates how a caller will handle the possibility of resources not being available. If sleep_flag is DDI_NOSLEEP, then it does not matter if allocation fails or the queue is full; the caller will handle such a failure appropriately. If sleep_flag is set to DDI_SLEEP, the caller will have allocation and queuing routines wait for resources to become available.

The following example demonstrates how ddi_log_sysevent() is used.

char *vendor_name = "DDI_VENDOR_JGJG"
char *my_class = "EC_ENVIRONMENT";
char *my_subclass = "ESC_TEMPERATURE";
nvlist_t *nvl;
...
nvl = create_nvlist();
...
     /* an event occurs... */ ...
        if (ddi_log_sysevent(dip, vendor_name, my_class, 
            my_subclass, nvl, NULL, DDI_SLEEP)!= DDI_SUCCESS)
                 cmn_err(CE_WARN, "error logging system event"); 

Event Name-Value Pairs

For interfaces such as ddi_log_sysevent(9F), the Solaris DDI provides a way to store information in name-value pairs. Name-value pairs are retained in an nvlist_t structure, which is opaque to the driver.

The value for a name-value pair may be a boolean, an int (16, 32, and 64-bit, signed or unsigned), a string, or an array of ints, bytes, or strings.

The steps in creating a list of name-value pairs are as follows.

  1. Create an nvlist_t structure with nvlist_alloc(9F).

    The nvlist_alloc(9F) interface takes three arguments. The first is a pointer to an nvlist_t structure.

    The second is a flag relating to the uniqueness of the names of the pairs. If this flag is set to NV_UNIQUE_NAME_TYPE, any existing pair in the list will be removed if a new pair with the same name and type is added. If the flag is set to NV_UNIQUE_NAME, then any existing pair with the same name as one being added will be removed, regardless of its type. Specifying NV_UNIQUE_NAME_TYPE allows a list to contain two or more pairs with the same name, as long as their types are different, whereas with NV_UNIQUE_NAME only one instance of a pair name can be in the list. If neither value is used, then no uniqueness checking is done, and the consumer of the list must parse it in such a way as to ensure that any pair retrieved is the one wanted.

    The third argument relates to kernel memory allocation policy. If it is set to KM_SLEEP, then the driver will block until the requested memory is available for allocation. KM_SLEEP allocations may sleep but are guaranteed to succeed. KM_NOSLEEP allocations are guaranteed not to sleep but may fail (return NULL ) if no memory is currently available.

  2. Populate the nvlist with name-value pairs. For example, to add a string, use nvlist_add_string(9F); to add an array of 32-bit integers, use nvlist_add_int32_array(9F). The nvlist_add_boolean(9F) man page contains a complete list of interfaces for adding pairs.

To deallocate a list, use nvlist_free(9F).


Example 4-2 Creating and Populating a Name-Value Pair List

nvlist_t*
create_nvlist()
        {
        int err;
        char *str = "child";
        int32_t ints[] = {0, 1, 2};
        nvlist_t *nvl;
        err = nvlist_alloc(&nvl, 0);    /* allocate list */
        if (err)
                return (NULL);
        /* name="child" & prop={0, 1, 1} */
        if ((nvlist_add_string(nvl, "name", str) != 0) ||
            (nvlist_add_int32_array(nvl, "prop", ints, 3) != 0)) {
                    nvlist_free(nvl);
                    return (NULL);
        }
        return (nvl);
}

Drivers can retrieve the elements of an nvlist by using a lookup function for that type, such as nvlist_lookup_int32_array(9F), which takes as its arguments the name and type of the pair being searched for. Note, however, that these interfaces will only work if either NV_UNIQUE_NAME or NV_UNIQUE_NAME_TYPE was specified when nvlist_alloc(9F) was called.

Name-value lists can be placed in contiguous memory (for example, to pass them to another process or send them to another host). To do so, first get the size of the memory block needed for the list with nvlist_size(9F), and then pack the list into the buffer with nvlist_pack(9F). The consumer receiving the buffer's content can unpack the buffer with nvlist_unpack(9F).

 
 
 
  Previous   Contents   Next