fp_select Kernel Service

Purpose

Provides for cascaded, or redirected, support of the select or poll request.

Syntax

#include <sys/types.h> #include <sys/errno.h> int fp_select ( fp, events, rtneventp, notify) struct file *fp; ushort events; ushort *rtneventp; void (*notify)();

Parameters

Item Description
fp Points to the open instance of the device driver, socket, or pipe for which the low-level select operation is intended.
events Identifies the events that are to be checked. There are three standard event flags defined for the poll and select functions and one informational flag. The /usr/include/sys/poll.h file details the event bit definition. The four basic indicators are:
POLLIN
Input is present for the specified object.
POLLOUT
The specified file object is capable of accepting output.
POLLPRI
An exception condition has occurred on the specified object.
POLLSYNC
This is a synchronous request only. If none of the requested events are true, the selected routine should not remember this request as pending. That is, the routine does not need to call the selnotify service because of this request.
rtneventp Indicates the returned events pointer. This parameter, passed by reference, is used to indicate which selected events are true at the current time. The returned event bits include the requested events plus an additional error event indicator:
POLLERR
An error condition was indicated by the object's select routine. If this flag is set, the nonzero return code from the specified object's select routine is returned as the return code from the fp_select kernel service.
notify Points to a routine to be called when the specified object invokes the selnotify kernel service for an outstanding asynchronous select or poll event request. If no routine is to be called, this parameter must be NULL.

Description

The fp_select kernel service is a low-level service used by kernel extensions to perform a select operation for an open device, socket, or named pipe. The fp_select kernel service can be used for both synchronous and asynchronous select requests. Synchronous requests report on the current state of a device, and asynchronous requests allow the caller to be notified of future events on a device.

Invocation from a Device Driver's ddselect Routine

A device driver's ddselect routine can call the fp_select kernel service to pass select/poll requests to other device drivers. The ddselect routine for one device invokes the fp_select kernel service, which calls the ddselect routine for a second device, and so on. This is required when event information for the original device depends upon events occurring on other devices. A cascaded chain of select requests can be initiated that involves more than two devices, or a single device can issue fp_select calls to several other devices.

Each ddselect routine should preserve, in its call to the fp_select kernel service, the same POLLSYNC indicator that it received when previously called by the fp_select kernel service.

Invocation from Outside a Device Driver's ddselect Routine

If the fp_select kernel service is invoked outside of the device driver's ddselect routine, the fp_select kernel service sets the POLLSYNC flag, always making the request synchronous. In this case, no notification of future events for the specified device occurs, nor is a notify routine called, if specified. The fp_select kernel service can be used in this manner (unrelated to a poll or select request in progress) to check an object's current status.

Asynchronous Processing and the Use of the notify Routine

For asynchronous requests, the fp_select kernel service allows its callers to register a notify routine to be called by the kernel when specified events become true. When the relevant device driver detects that one or more pending events have become true, it invokes the selnotify kernel service. The selnotify kernel service then calls the notify routine, if one has been registered. Thus, the notify routine is called at interrupt time and must be programmed to run in an interrupt environment.

Use of a notify routine affects both the calling sequence at interrupt time and how the requested information is actually reported. Generalized asynchronous processing entails the following sequence of events:

  1. A select request is initiated on a device and passed on (by multiple fp_select kernel service invocations) to further devices. Eventually, a device driver's ddselect routine that is not dependent on other devices for information is reached. This ddselect routine finds that none of the requested events are true, but remembers the asynchronous request, and returns to the caller. In this way, the entire chain of calls is backed out, until the origin of the select request is reached. The kernel then puts the originating process to sleep.
  2. Later, one or more events become true for the device remembering the asynchronous request. The device driver routine (possibly an interrupt handler) calls the selnotify kernel service.
  3. If the events are still being waited on, the selnotify kernel service responds in one of two ways. If no notify routine was registered when the select request was made for the device, then all processes waiting for events on this device are awakened. If a notify routine exists for the device, then this routine is called. The notify routine determines whether the original requested event should be reported as true, and if so, calls the selnotify kernel service on its own.

The following example details a cascaded scenario involving several devices. Suppose that a request has been made for Device A, and Device A depends on Device B, which depends on Device C. When specified events become true at Device C, the selnotify kernel service called from Device C's device driver performs differently depending on whether a notify routine was registered at the time of the request.

Cascaded Processing without the Use of notify Routines

If no notify routine was registered from Device B, then the selnotify kernel service determines that the specified events are to be considered true for the device driver at the head of the cascading chain. (The head of the chain, in this case Device A, is the first device driver to issue the fp_select kernel service from its select routine.) The selnotify kernel service awakens all processes waiting for events that have occurred on Device A.

It is important to note that when no notify routine is used, any device driver in the calling chain that reports an event with the selnotify kernel service causes that event to appear true for the first device in the chain. As a result, any processes waiting for events that have occurred on that first device are awakened.

Cascaded Processing with notify Routines

If, on the other hand, notify routines have been registered throughout the chain, then each interrupting device (by calling the selnotify kernel service) invokes the notify routine for the device above it in the calling chain. Thus in the preceding example, the selnotify kernel service for Device C calls the notify routine registered when Device B's ddselect routine invoked the fp_select kernel service. Device B's notify routine must then decide whether to again call the selnotify kernel service to alert Device A's notify routine. If so, then Device A's notify routine is called, and makes its own determination whether to call another selnotify routine. If it does, the selnotify kernel service wakes up all the processes waiting on occurred events for Device A.

A variation on this scenario involves a cascaded chain in which only some device drivers have registered notify routines. In this case, the selnotify kernel service at each level calls the notify routine for the level above, until a level is encountered for which no notify routine was registered. At this point, all events of interest are determined to be true for the device driver at the head of the cascading chain. If any notify routines were registered in levels above the current level, they are never called.

Returning from the fp_select Kernel Service

The fp_select kernel service does not wait for any selected events to become true, but returns immediately after the call to the object's ddselect routine has completed.

If the object's select routine is successfully called, the return code for the fp_select kernel service is set to the return code provided by the object's ddselect routine.

Execution Environment

The fp_select kernel service can be called from the process environment only.

Return Values

Item Description
0 Indicates successful completion.
EAGAIN Indicates that the allocation of internal data structures failed. The rtneventp parameter is not updated.
EINVAL Indicates that the fp parameter is not a valid file pointer. The rtneventp parameter has the POLLNVAL flag set.

The fp_select kernel service can also be set to the nonzero return code from the specified object's ddselect routine. The rtneventp parameter has the POLLERR flag set.