Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ srv(D2) — UnixWare 2.01

Media Vault

Software Library

Restoration Projects

Artifacts Sought






       srv(D2)                                                      srv(D2)


       NAME
             srv - service queued messages

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

          Arguments
             q     Pointer to the queue.

       DESCRIPTION
             The srv (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.  The
             service routine also provides a way to recover from resource
             allocation failures.

          Return Values
             Ignored

       USAGE
             This entry point is optional, and is valid for STREAMS drivers
             and modules only.

             A message is first passed to a module's or driver's put(D2)
             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(D4)] has limit values it uses
             to implement flow control.  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


                           Copyright 1994 Novell, Inc.               Page 1













      srv(D2)                                                      srv(D2)


            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 provide for processing all messages on its queue,
            restarting itself if necessary.  Message processing must
            continue 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.

            For singlethreaded modules and drivers, the framework for the
            canonical service procedure algorithm is as follows:
                  queue_t *q;
                  mblk_t *mp;
                  while ((mp = getq(q)) != NULL) {
                        if (mp->b_datap->db_type > QPCTL ||
                           canput(q->q_next)) {
                              /* process the message */
                              putnext(q, mp);
                        } else {
                              putbq(q, mp);
                              return;
                        }
                  }

            If the singlethreaded module or driver cares about priority
            bands, the algorithm becomes:
                  queue_t *q;
                  mblk_t *mp;
                  while ((mp = getq(q)) != NULL) {


                          Copyright 1994 Novell, Inc.               Page 2













       srv(D2)                                                      srv(D2)


                         if (mp->b_datap->db_type > QPCTL ||
                            bcanput(q->q_next, mp->b_band)) {
                               /* process the message */
                               putnext(q, mp);
                         } else {
                               putbq(q, mp);
                               return;
                         }
                   }

             For multithreaded modules and drivers, 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 multithreaded 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;
                         }
                   }

             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 the module's qinit(D4) structure.




                           Copyright 1994 Novell, Inc.               Page 3













      srv(D2)                                                      srv(D2)


            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(D3)] at some later time [see
            bufcall(D3) and timeout(D3)].

            Service routines can be interrupted by put routines, unless
            the processor interrupt level is raised.

            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(D3) should be used to schedule service routines to
            run.

            Drivers (excepting multiplexors) 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.

         Synchronization Constraints
            Service routines do not have user context and so may not call
            any function that sleeps.

      REFERENCES
            bcanput(D3), bcanputnext(D3), bufcall(D3), canput(D3),
            canputnext(D3), datab(D4), getq(D3), msgb(D4), pcmsg(D3),
            put(D2), putbq(D3), putnext(D3), putq(D3), qenable(D3),
            qinit(D4), queue(D4), timeout(D3)




                          Copyright 1994 Novell, Inc.               Page 4













       srv(D2)                                                      srv(D2)


       NOTICES
          Portability
             All processors

          Applicability
             ddi: 1, 2, 3, 4, 5, 5mp, 6, 6mp, 7, 7mp










































                           Copyright 1994 Novell, Inc.               Page 5








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