|
|
#include <sys/types.h> #include <sys/stream.h> #include <sys/stropts.h> #include <sys/ddi.h>int prefixrput(queue_t *q, mblk_t *mp); /* read side */
int prefixwput(queue_t *q, mblk_t *mp); /* write side */
Both modules and drivers must have write put routines. Modules must have read put routines, but drivers don't really need them because their interrupt handler can do the work intended for the read put routine. A message is passed to the put routine. If immediate processing is desired, the put routine can process the message, or it can enqueue it so that the srv(D2str) service routine can process it later.
The put routine must do at least one of the following when it receives a message:
Typically,
the put routine switches on the message type,
which is contained in mp->b_datap->db_type
,
taking different actions depending on the message type.
For example, a put routine
might process high priority messages
and enqueue normal messages.
The putq function can be used as a module's put routine when no special processing is required and all messages are to be enqueued for the service routine.
Drivers and modules usually handle queue flushing in their put routines, although it can be done in the service routine.
Multithreaded drivers must not hold locks when passing messages to other queues in the stream.
With multithreaded drivers, multiple copies of the same put routine for a given queue, as well as the service routine for the queue, can be running concurrently. Drivers and modules are responsible for synchronizing access to their own private data structures accordingly.
oddi: 1, 2, 2mp, 3, 3mp, 4, 4mp, 5, 5mp
The canonical flushing algorithm for driver write put routines is as follows:
queue_t *q; /* the write queue */ if (*mp->b_rptr & FLUSHBAND) { /* if driver recognizes bands */ if (*mp->b_rptr & FLUSHW) { flushband(q, FLUSHDATA, *(mp->b_rptr + 1)); *mp->b_rptr &= ~FLUSHW; } if (*mp->b_rptr & FLUSHR) { flushband(RD(q), FLUSHDATA, *(mp->b_rptr + 1)); qreply(q, mp); } else { freemsg(mp); } } else { if (*mp->b_rptr & FLUSHW) { flushq(q, FLUSHDATA); *mp->b_rptr &= ~FLUSHW; } if (*mp->b_rptr & FLUSHR) { flushq(RD(q), FLUSHDATA); qreply(q, mp); } else { freemsg(mp); } }
The canonical flushing algorithm for module write put routines is as follows:
queue_t *q; /* the write queue */ if (*mp->b_rptr & FLUSHBAND) { /* if module recognizes bands */ if (*mp->b_rptr & FLUSHW) flushband(q, FLUSHDATA, *(mp->b_rptr + 1)); if (*mp->b_rptr & FLUSHR) flushband(RD(q), FLUSHDATA, *(mp->b_rptr + 1)); } else { if (*mp->b_rptr & FLUSHW) flushq(q, FLUSHDATA); if (*mp->b_rptr & FLUSHR) flushq(RD(q), FLUSHDATA); } if (!SAMESTR(q)) { switch (*mp->b_rptr & FLUSHRW) { case FLUSHR: *mp->b_rptr = (*mp->b_rptr & ~FLUSHR) | FLUSHW; break; case FLUSHW: *mp->b_rptr = (*mp->b_rptr & ~FLUSHW) | FLUSHR; break; } } putnext(q, mp);
The algorithms for the read side are similar. In both examples, the FLUSHBAND flag need only be checked if the driver or module cares about priority bands.
Drivers and modules should not call put routines directly.
Drivers should free any messages they do not recognize.
Modules should pass on any messages they do not recognize.
Drivers should fail any unrecognized M_IOCTL(D7str) messages by converting them into M_IOCNAK(D7str) messages and sending them upstream.
Modules should pass on any unrecognized M_IOCTL messages.