Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ srv(D2DK) — Motorola System V 88k Release 4 Version 4.3

Media Vault

Software Library

Restoration Projects

Artifacts Sought

srv(D2DK)  —  

.IX \f4srv\fP(D2DK)

NAME

srv − service queued messages

SYNOPSIS

#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
int prefixrsrv(queue_t ∗q);  /∗ read side ∗/
int prefixwsrv(queue_t ∗q);  /∗ write side ∗/

ARGUMENTS

qPointer to the queue. 

DESCRIPTION

The service routine may be included in a STREAMS module or driver for a number of reasons.  It provides greater control over the flow of messages in a stream by allowing the module or driver to reorder messages, defer the processing of some messages, or fragment and reassemble messages.  Service routines also provide a way to recover from resource allocation failures. 

A message is first passed to a module’s or driver’s put(D2DK) routine, which may or may not process it.  The put routine can place the message on the queue for processing by the service routine. 

Once a message has been enqueued, the STREAMS scheduler calls the service routine at some later time.  Drivers and modules should not depend on the order in which service procedures are run.  This is an implementation-dependent characteristic.  In particular, applications should not rely on service procedures running before returning to user-level processing. 

Every STREAMS queue [see queue(D4DK)] 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 queues with service routines.  Flow control occurs by service routines following certain rules before passing messages along.  By convention, high priority messages are not affected by flow control. 

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 band zero) messages and high priority messages (such as M_IOCACK).  High priority messages are always placed at the head of the queue, after any other high priority messages already enqueued.  Next are messages from all included priority bands, which are enqueued in decreasing order of priority.  Each priority band has its own flow control limits.  By convention, if a band is flow-controlled, all lower priority bands are also stopped. 

Once a service routine is called by the STREAMS scheduler it must process all messages on its queue, until either the queue is empty, the stream is flow-controlled, or an allocation error occurs.  Typically, the service routine will switch on the message type, which is contained in mp->b_datap->db_type, taking different actions depending on the message type.  The framework for the canonical service procedure algorithm is as follows:

queue_t ∗q;
mblk_t ∗mp;
while ((mp = getq(q)) != NULL) {
if (pcmsg(mp->b_datap->db_type) ||
   canputnext(q) {
/∗ process the message ∗/
putnext(q, mp);
} else {
putbq(q, mp);
return;
}
}

If the module or driver cares about priority bands, the algorithm becomes:

queue_t ∗q;
mblk_t ∗mp;
while ((mp = getq(q)) != NULL) {
if (pcmsg(mp->b_datap->db_type) ||
   bcanputnext(q, mp->b_band)) {
/∗ process the message ∗/
putnext(q, mp);
} else {
putbq(q, mp);
return;
}
}

NOTES

This entry point is optional for modules and drivers, but multiplexing drivers are required to implement service routines for the upper and lower halves of the multiplexor.  Furthermore, the only safe way to transfer messages between the upper and lower halves is to use putq(D3DK), getq(D3DK), putbq(D3DK), insq(D3DK), or rmvq(D3DK).  In other words, multiplexing drivers must employ their service procedures to transfer messages between their upper and lower halves (that is, putnext(D3DK) cannot be called).  Each STREAMS module and driver can have a read and write service routine. If a service routine is not needed (because the put routine processes all messages), a NULL pointer should be placed in module’s qinit(D4DK) structure.  If the service routine finishes running because of any reason other than flow control or an empty queue, then it must explicitly arrange for its rescheduling. For example, if an allocation error occurs during the processing of a message, the service routine can put the message back on the queue with putbq, and, before returning, arrange to have itself rescheduled [see qenable(D3DK)] at some later time [see bufcall(D3DK) and timeout(D3DK)].  Service routines do not have user context and so may not call any function that sleeps. put routines can interrupt and run concurrently with service routines.  Only one copy of a queue’s service routine will run at a time. Drivers and modules should not call service routines directly. qenable(D3DK) should be used to schedule service routines to run.  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.  Service routines should never put high priority messages back on their queues.

RETURN VALUE

Ignored. 

SEE ALSO

STREAMS Programmer’s Guide

put(D2DK), bcanputnext(D3DK), bufcall(D3DK), canputnext(D3DK), getq(D3DK), pcmsg(D3DK), putbq(D3DK), putnext(D3DK), putq(D3DK), qenable(D3DK), timeout(D3DK), datab(D4DK), msgb(D4DK), qinit(D4DK), queue(D4DK)

DDI/DKI  —  STREAMS

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026