put(D2) put(D2)
NAME
put - 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
Copyright 1994 Novell, Inc. Page 1
put(D2) put(D2)
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.
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);
}
}
Copyright 1994 Novell, Inc. Page 2
put(D2) put(D2)
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 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.
Copyright 1994 Novell, Inc. Page 3
put(D2) put(D2)
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.
REFERENCES
datab(D4), flushband(D3), flushq(D3), msgb(D4), putctl(D3),
putctl1(D3), putnext(D3), putq(D3), qreply(D3), queue(D4),
srv(D2)
NOTICES
Portability
All processors
Applicability
ddi: 1, 2, 3, 4, 5, 5mp, 6, 6mp, 7, 7mp
Copyright 1994 Novell, Inc. Page 4