SELECT(K) UNIX System V SELECT(K)
Name
select: selsuccess, selfailure, selwakeup - kernel routines
supporting select(S)
Syntax
#include "sys/select.h"
void selsuccess()
void selfailure()
void selwakeup(proc-ptr, flags)
struct proc *proc-ptr;
char flags;
Description
The select(S) system call code sends a unique I/O control
command to the driver to ask whether or not a condition is
satisfied for reading, writing, or exceptional
circumstances. The mode argument to the xxioctl call
indicates the condition being selected, and has these values
which are defined in sys/select.h: SELREAD, SELWRITE, and
SELEXCEPT. All drivers that support select must implement
the IOC_SELECT ioctl with code similar to that displayed in
the example section in this manual page.
Drivers supporting select(S) must include global
declarations like the following:
#include "sys/select.h"
extern int selwait;
struct xx_selstr
{
struct proc *read;
struct proc *write;
struct proc *except;
char flags;
}
xxselstr[NUM_MINOR_DEVS];
A driver uses selfailure to indicate that the condition
which the user has selected is not true, and the process
should block.
A driver uses selsuccess to indicate that the condition
which the user has selected is true, and the process should
not block.
A driver uses selwakeup to indicate that the condition the
user selected which was not initially satisfied, is now
true. The process should now be awakened.
Parameters
procp is a pointer to a process table entry which is found
in the xxselstr data structure. Each time a process selects
a condition that is not immediately satisfied, a pointer to
the process is stored in the data structure. This pointer is
passed to the select(S) system call by the selwakeup call.
flags is a byte used to indicating if multiple processes are
colliding by selecting the same condition. Whenever more
than one process selects a condition, the driver must set
the correct collision bit. The three bits defined in
sys/select.h are: READ_COLLISION, WRITE_COLLISION, and
EXCEPT_COLLISION, for selecting for reading, writing, and
exceptional conditions, respectively.
Examples
In the first example, a process issues the select(S) system
call (read case only): Note that the examples can be
replicated identically substituting write and except for all
occurrences of read.
/*
* This routine from driver xx
* handles a select for read request.
* Note all requests come from
* the select system call individually.
*/
xxioctl(dev, cmd, mode, arg)
dev_t dev;
int cmd, mode, arg;
{
...
if ( cmd == IOC_SELECT )
{
switch (mode)
{
case SELREAD: xx_selread(dev);
break;
/*
* likewise for SELWRITE and SELEXCEPT
*/
}
return;
}
...
/*
* Normal ioctl processing
*/
}
xx_selread(dev)
dev_t dev;
{
extern void selsuccess();
extern void selfailure();
struct proc *procp;
struct xx_selstr *ptr = &xxselstr[dev];
if ( xx_condition_is_satisfied_for_read[dev] )
{
selsuccess();
return;
}
/*
* Condition is unsatisfied; process will block.
*/
procp = ptr->read;
if ( procp && procp->p_wchan == (char*) &selwait )
ptr->flags |= READ_COLLISION;
else
ptr->read = u.u_procp;
selfailure();
}
In the next example, the process has selected a condition
and is blocked. Then, the condition becomes satisfied (read
case handled):
xxintr(level)
{
...
/*
* Driver first notices that the condition is now
* satisfied and computes minor dev
*/
xxwakeread(dev);
...
}
xxwakeread(dev)
dev_t dev;
{
struct xx_selstr *ptr = &xxselstr[dev];
/*
* If a proc has selected the condition, awaken it.
*/
if ( ptr->read )
{
selwakeup(ptr->read, ptr->flags
& READ_COLLISION);
ptr->read = (struct proc *) NULL;
ptr->flags &= ~READ_COLLISION;
}
}
(printed 7/6/89)