|
|
#include <sys/select.h>void selsuccess(void);
void selfailure(void);
void selwakeup(struct proc
proc_ptr, long flags);
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.
selfailure( ) indicates that the condition selected by the user is not true
selsuccess( ) indicates that the condition selected by the user is true
selwakeup( ) indicates that the condition selected by the user and that was not initially satisfied is now true.
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];
/*
* This routine from driver xx handles a select for read
* request. Note all requests come from the select system
* call individually.
*/
xxioctl(dev_t dev, int cmd, int arg, int mode);
{
...
if (cmd == IOC_SELECT)
{
switch (mode)
{
case SELREAD: xx_selread(dev);
break;
/*
* likewise for SELWRITE and SELEXCEPT
*/
}
return;
}
...
/* * Normal ioctl processing */ }In the next example, the process has selected a condition and is blocked. Then, the condition becomes satisfied (read case handled):xx_selread(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(); }
xxintr(level)
{
...
/*
* Driver first notices that the condition is now
* satisfied and computes minor dev
*/
xxwakeread(dev);
...
}
xxwakeread(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;
}
}