The procedures in the QUEUE are the software routines that process messages as they transit the QUEUE. The processing is generally performed according to the message type and can result in a modified message, new messages, or no message. A resultant message is generally sent in the same direction in which it was received by the QUEUE, but may be sent in either direction. A QUEUE always contains a put procedure and may also contain an associated service procedure.
A put procedure is the QUEUE routine that receives messages from the preceding QUEUE in the stream. Messages are passed between QUEUEs by a procedure in one QUEUE calling the put procedure contained in the following QUEUE. A call to the put procedure in the appropriate direction is generally the only way to pass messages between modules. (Unless otherwise indicated, the term modules implies a module, driver, and stream head.) QUEUEs in pushable modules contain a put procedure. In general, there is a separate put procedure for the read and write QUEUEs in a module because of the full-duplex operation of most streams.
A put procedure is associated with immediate (as opposed to deferred) processing on a message. Each module accesses the adjacent put procedure as a subroutine. For example, suppose that modA, modB, and modC are three consecutive modules in a stream, with modC connected to the stream head. If modA receives a message to be sent upstream, modA processes that message and then calls the modB put procedure. The modB procedure processes the message and then calls the modC put procedure. Finally, the modC procedure processes the message and then calls the stream-head put procedure.
Thus, the message will be passed along the stream in one continuous processing sequence. This sequence has the benefit of completing the entire processing in a short time with low overhead (subroutine calls). However, it may not be desirable to use this manner of processing if this sequence is lengthy and the processing is implemented on a system with multiple users. Using this manner of processing under those circumstances may be good for this stream but detrimental to other streams since they may have to wait a long time to be processed.
In addition, some situations exist where the put procedure cannot immediately process the message but must hold it until processing is allowed. The most typical examples of this are a driver (which must wait until the current output completes before sending the next message) and the stream head (which may have to wait until a process initiates the read subroutine on the stream).
STREAMS allows a service procedure to be contained in each QUEUE, in addition to the put procedure, to address the above cases and for either purposes. A service procedure is not required in a QUEUE and is associated with deferred processing. If a QUEUE has both a put and service procedure, message processing will generally be divided between the procedures. The put procedure is always called first, from a preceding QUEUE. After the put procedure completes its part of the message processing, it arranges for the service procedure to be called by passing the message to the putq utility. The putq utility does two things: it places the message on the message queue of the QUEUE, and it links the QUEUE to the end of the STREAMS scheduling queue. When the putq utility returns to the put procedure, the procedure typically exits. Some time later, the service procedure will be automatically called by the STREAMS scheduler.
The STREAMS scheduler is separate and distinct from the system process scheduler. It is concerned only with QUEUEs linked on the STREAMS scheduling queue. The scheduler calls the service procedure of the scheduled QUEUE one at a time, in a FIFO manner.
Having both a put and service procedure in a QUEUE enables STREAMS to provide the rapid response and the queuing required in systems with many users. The put procedure allows rapid response to certain data and events, such as software echoing of input characters. Put procedures effectively have higher priority than any scheduled service procedures. When called from the preceding STREAMS component, a put procedure starts before the scheduled service procedures of any QUEUE are started.
The service procedure implies message queuing. Queuing results in deferred processing of the service procedure, following all other QUEUEs currently on the scheduling queue. For example, terminal output, input erase, and kill processing would typically be performed in a service procedure because this type of processing does not have to be as timely as echoing. Using a service procedure also allows processing time to be more evenly spread among multiple streams. As with the put procedure, there will generally be a separate service procedure for each QUEUE in a module. The flow-control mechanism uses the service procedures.