|
|
#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; } }