put(D2)put(D2)NAMEput - receive messages from the preceding queue
SYNOPSIS
#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 */
Arguments
q Pointer to the queue.
mp Pointer to the message block.
DESCRIPTION
The primary task of the put routine is to coordinate the passing of
messages from one queue to the next in a stream. The put routine is
called by the preceding component (module, driver, or stream head) in the
stream. put routines are designated ``write'' or ``read'' depending on
the direction of message flow.
Return Values
Ignored
USAGE
This entry point is required in all STREAMS drivers and modules.
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 service routine [see srv(D2)] can process it later.
The put routine must do at least one of the following when it receives a
message:
pass the message to the next component in the stream by calling the
putnext(D3) function
process the message, if immediate processing is required (for
example, high priority messages)
enqueue the message with the putq(D3) function for deferred
processing by the service routine
Typically, the put routine will switch 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.
Page 1
put(D2)put(D2)
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.
Although it can be done in the service routine, drivers and modules
usually handle queue flushing in their put routines.
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) {
Page 2
put(D2)put(D2)
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 messages by converting them
into M_IOCNAK messages and sending them upstream.
Modules should pass on any unrecognized M_IOCTL messages.
Synchronization Constraints
put routines do not have user context and so may not call any function
that sleeps.
REFERENCESdatab(D4), flushband(D3), flushq(D3), msgb(D4), putctl(D3), putctl1(D3),
putnext(D3), putq(D3), qreply(D3), queue(D4), srv(D2)
Page 3