put(D2DK) —
.IX \f4put\fP(D2DK)
NAME
put − receive messages from the preceding queue
SYNOPSIS
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.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.
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(D2DK)] 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(D3DK) function.
Process the message, if immediate processing is required (for example, high priority messages.)
Enqueue the message with the putq(D3DK) 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.
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) {
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.
NOTES
This entry point is required.
put routines do not have user context and so may not call any function that sleeps.
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.
No locks should be held when passing messages to other queues in the stream.
put procedures cannot be called directly. Drivers can use put(D3DK) for this purpose.
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.
RETURN VALUE
Ignored.
SEE ALSO
STREAMS Programmer’s Guide
srv(D2DK), flushband(D3DK), flushq(D3DK), putctl(D3DK), putctl1(D3DK), putnext(D3DK), putq(D3DK), qreply(D3DK), datab(D4DK), msgb(D4DK), queue(D4DK)
DDI/DKI — STREAMS