'\"macro stdmacro
.if n .pH ddi_dki.srv @(#)srv	40.7 of 1/3/90
.\" Copyright 1989 AT&T
.de IX
.ie '\\n(.z'' .tm .Index: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9	\\n%
.el \\!.IX \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
..
.nr X
.if \nX=0 .ds x} srv D2DK "STREAMS" "DDI/DKI" "\&"
.if \nX=1 .ds x} srv D2DK "STREAMS" "DDI/DKI"
.if \nX=2 .ds x} srv D2DK "" "\&"
.if \nX=3 .ds x} srv "" "" "\&"
.TH \*(x}
.IX "\f4srv\fP(D2DK)"
.SH NAME
\f4srv\f1 \- service queued messages
.SH SYNOPSIS
.nf
.na
\f4
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
.sp 0.5
void \f2prefix\f4rsrv(\f4queue_t\f1 \f2q\f4);  /* read side */
.sp 0.5
void \f2prefix\f4wsrv(\f4queue_t\f1 \f2q\f4);  /* write side */
.ad
.fi
.SH ARGUMENTS
.RS 0n 5n
.IP "\f2*q\f1" 10n
Pointer to the \f4queue\f1(D4DK) structure
.RE
.SH DESCRIPTION
The optional service (\f4srv\f1) routine
may be included in a STREAMS module or driver for one or more of the
following reasons:
.IP
to provide greater control over the
flow of messages in a stream
.IP
to make it possible to defer the processing of some messages
to avoid depleting system resources
.IP
to combine small messages into larger ones, or break
large messages into smaller ones
.IP
to recover from resource allocation failure.
A module's or driver's \f4put\f1(D3DK) routine can test for the
availability of a resource, and if it is not available,
enqueue the message for later processing by the \f4srv\f1 routine.
.P
A message is first passed to a module's or driver's
\f4put\f1(D2DK) routine, which may or may not do some processing.
It must then either
.IP
pass the message to the next stream component
with \f4putnext\f1(D3DK)
.IP
if a \f4srv\f1 routine has been included, it may call
the \f4putq\f1(D3DK) function to place the
message on the queue
.P
Once a message has been enqueued, the STREAMS scheduler 
controls the calling of the service routine.
Service routines are called in FIFO order by the scheduler.
No guarantees can be made about how long it will take for a
\f4srv\f1 routine to be called except that it will happen before
any user level process are run.
.P
Every stream component (stream head, module or driver) has limit
values it uses to implement flow control.
Tunable high and low water marks are checked to stop and restart
the flow of message processing.
Flow control limits apply only between two adjacent components
with \f4srv\f1 routines.
.P
STREAMS messages can be defined to have up to 256 different
priorities to support some networking protocol requirements
for multiple bands of data flow.
At a minimum, a stream must distinguish between normal (priority
zero) messages and high priority messages (such as \f4M_IOCACK\f1).
High priority messages are always placed at the head of the \f4srv\f1
routine's queue, after any other enqueued high priority messages.
Next are messages from all included priority bands,\p
.br
.ne .5i
which are enqueued in decreasing
order of priority.
Each priority band has its own flow control limits.
If a flow controlled band is stopped, all lower priority bands are
also stopped.
.P
Once a \f4srv\f1 routine is called by the STREAMS scheduler it must
process all messages on its queue.
The following steps are general guidelines for processing messages.
Keep in mind that many of the details of how a \f4srv\f1 routine
should be written depend of the implementation, the direction of
flow (upstream or downstream), and whether it is for a module or a
driver.
.P
.RS 2n
.TP 4n
1.
Use the \f4getq\f1(D3DK) function to get the next enqueued message.
.TP
2.
If the message is high priority, process (if appropriate)
and pass to the next stream
component with the \f4putnext\f1(D3DK) function.
.TP
3.
If it is not a high priority message (and therefore subject to
flow control), attempt to send it to the next stream component 
with a \f4srv\f1 routine.  
Use \f4bcanput\f1(D3DK) to determine if this
can be done.
.TP
4.
If the message cannot be passed, put it back on the queue with
\f4putbq\f1(D3DK).
If it can be passed, process (if appropriate) 
and pass with \f4putnext\f1.
.RE
.P
\f3NOTE:\f1
Each stream module has a read and write service (\f4srv\f1) routine.
If a service routine is not needed (because the \f4put\f1 routine
processes all messages), a \f4NULL\f1 pointer should be placed
in module's \f4qinit\f1 structure.
Do not use the \f4nulldev\f1 routine instead of the \f4NULL\f1
pointer.  Use of \f4nulldev\f1 for a \f4srv\f1 routine 
may result in flow control errors.
.SH SEE ALSO
The \f2BCI Driver Development Guide\f1, Chapter 7, ``STREAMS''
.P
The \f2STREAMS Programmer's Guide\f1, Chapter 5, ``Messages''
.P
.na
\f4bcanput\f1(D3DK),
\f4canput\f1(D3DK),
\f4getq\f1(D3DK),
\f4put\f1(D2DK),
\f4putbq\f1(D3DK),
\f4putnext\f1(D3DK),
\f4putq\f1(D3DK),
\f4queue\f1(D4DK)
.ad
