HPlogo STREAMS/UX for the HP 9000 Reference Manual > Chapter 3 Differences Between STREAMS/UX and System V Release 4 STREAMS

STREAMS/UX Uniprocessor Synchronization

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

This section describes STREAMS/UX synchronization on a uniprocessor system. Chapter 4 discusses multiprocessor synchronization. Also, Chapter 4 describes how modules and drivers running on a uniprocessor system can use multiprocessor synchronization mechanisms to protect against interrupts. STREAMS/UX programmers must follow the guidelines listed below as well as those in the SVR4.2 STREAMS manual.

STREAMS/UX provides the following types of synchronization on a uniprocessor system:

  • STREAMS/UX protects its internal data structures from interrupts.

  • STREAMS/UX helps protect module and driver private data structures against interrupts.

  • STREAMS/UX allows multiple processes to perform operations on the same stream.

  • The STREAMS/UX scheduler synchronizes the running of service routines with application processing.

STREAMS/UX Internal Synchronization

STREAMS/UX protects its internal data structures, such as message queues, against interrupts. STREAMS/UX programmers must use the following guidelines.

  1. A put, service, open, or close routine can pass its own queue or the other queue in its queue pair to a STREAMS/UX kernel utility. Many STREAMS/UX utilities operate on a queue. For example, getq takes a queue as an input parameter and returns a message from the queue. A service routine can only pass its queue or the other queue in its queue pair to getq. The restricted utilities are backq, bcanputnext, canputnext, flushband, flushq, freezestr, getq, insq, putbq, putnext, putnextctl, putnextctl1, putnextctl2, putq, qreply, qsize, rmvq, SAMESTR, strqget, strqset, and unfreezestr. The putq utility is not restricted when it is passed a driver's read queue or a lower mux's write queue. Any put or service routine can call putq if it passes it a driver's read queue or a lower mux's write queue. However, putq's caller must guarantee that the queue passed is still allocated. Some STREAMS/UX utilities, such as canput, are commonly passed a parameter of the form q->q_next. These routines are restricted in a slightly different way than those listed above. A put or service routine can only pass its own queue's q_next field or the q_next field of the other queue in its queue pair. These requirements apply to bcanput, canput, put, putctl, putctl1, putctl2, and streams_put. These utilities are not restricted when they are passed a parameter of the form q, except that the queue must still be allocated.

  2. Some STREAMS/UX utilities cannot be called from user functions passed to timeout and bufcall or from non-STREAMS/UX code in the kernel. Also, this software cannot share data structures with STREAMS/UX modules and drivers, unless it raises the spl level to protect against interrupts. The utilities which cannot be called are backq, bcanputnext, canputnext, flushband, flushq, freezestr, getq, insq, putbq, putnext, putnextctl, putnextctl1, putnextctl2, qreply, qsize, rmvq, SAMESTR, strqget, strqset, and unfreezestr. The user functions and non-STREAMS/UX code cannot call bcanput, canput, put, putctl1, putctl2, or streams_put if they pass the utility a parameter of the form q->q_next. They can call these utilities if they pass a parameter of the form q (q must be a valid, allocated queue). User functions and non-STREAMS/UX code can only call putq if they pass it a driver's read queue or a lower mux's write queue. User functions and non-STREAMS/UX code can use the new streams_put utility documented in this chapter to get around these restrictions.

  3. Some STREAMS/UX utilities cannot be called from free routines passed to esballoc. A free routine can call the same utilities as the module or driver entry point that called freeb.

  4. If a multiplexor can execute on the ICS, take care when using putnext to pass messages across the multiplexor. If the upper mux passes messages downward by passing the lower mux's write queue to putnext, the upper mux must ensure that the driver stays linked under the mux until after the putnext completes. Likewise, if the lower mux passes messages upward by passing the upper mux's read queue to putnext, the lower mux must guarantee that the driver stays linked under the mux, the mux stays open, and modules are not pushed or popped until after the putnext finishes.

  5. A protect_q parameter can be passed to the weldq utility. The protect_q parameter specifies which queue the func parameter can access safely. The func function can use the same STREAMS/UX utilities as the protect_q put and service routines.

  6. The put and service routines cannot be called directly. They must be executed by calling STREAMS/UX utilities such as putnext, putq or qenable. They cannot be called using the function pointer stored in the q_qinfo structure.

  7. Drivers and modules should not call STREAMS/UX utilities from software running on the interrupt control stack processing an spl6 or higher interrupt. STREAMS/UX protects its internal data structures using spl5.

Driver and Module Synchronization

Drivers and modules must protect their private data structures against interrupts. This can be done in four ways. One way would occur if software that is running on the interrupt control stack (ICS) modifies driver and module data structures. In this case, the driver and module service and put routines must raise the spl level before accessing their data structures. Drivers and modules can call the STREAMS/UX utility splstr to raise the spl level to spl5. Interrupts are masked while the spl level is raised.

The second way to protect data structures against interrupts is for software running on the ICS to send a message to a stream. If this is done, drivers and modules do not need to raise the spl level to protect their data. The software running on the ICS does a putq on the driver's read queue. The STREAMS scheduler will run the service routine off the ICS. When ICS software calls putq for a priority band, the driver open function must allocate the band by calling strqget. This prevents putq from dynamically allocating memory for the band on the ICS.

ICS software can call putnext or put instead of putq to send a message to a stream. If one of these utilities is called, STREAMS/UX will attempt to run the put routine on the ICS. Drivers and modules will need to use spl calls to protect data structures that they share with other drivers and modules, with other instances of the same driver or module, or with non-STREAMS/UX software.

The third way to protect data structures against interrupts is for interrupt software to call the qenable utility to schedule a service routine. The STREAMS/UX scheduler will run the service routine off the ICS.

The fourth method for protecting data structures against interrupts is to call the new streams_put utility. The code running on the ICS passes streams_put a function and a queue. STREAMS/UX runs the function as if it were the queue's put routine. The function can access the same data structures as the queue's put routine. See "HP-UX Modifications to STREAMS/UX Utilities" in this chapter for more information about streams_put.

Multiple Processes Accessing the Same Stream

STREAMS/UX synchronizes multiple processes that are accessing the same stream. Three scenarios will allow more than one process to operate on a stream:

  • Multiple processes opening a non-cloneable device with the same minor number

  • A process calling fork

  • Processes issuing I_SENDFD and I_RECVFD ioctls

For synchronization, STREAMS/UX will queue some open and ioctl system calls issued by different processes, and will execute them one at a time. STREAMS/UX queues re-opening an already open stream, and queues the following ioctls: I_PUSH, I_POP, I_LINK, I_PLINK, I_UNLINK, I_PUNLINK, I_FLUSH, I_FLUSHBAND, I_GETCLTIME, I_SETCLTIME, I_GETSIG, I_SETSIG, I_LIST, I_LOOK, and I_STR.

STREAMS/UX does not process a close call until the last file descriptor for a stream is closed. No other system calls will be executing when STREAMS/UX begins to dismantle the stream.

For remaining system calls, STREAMS/UX ensures that consistent results are returned, but the calls are not executed one at a time. For example, if two processes are reading from the same stream, one process could read the first and third messages on the stream to satisfy a read request while the second process reads the second and fourth messages.

The STREAMS/UX Scheduler

The STREAMS/UX scheduler runs service routines that are scheduled by STREAMS/UX utilities such as putq . The scheduler will run all scheduled service routines before returning to user level. The scheduler is a real time daemon that runs at priority 100. (A low priority number denotes a high priority. For example, a priority number of 50 would be of higher priority than the number 100.) STREAMS/UX applications need to run at a lower priority (higher priority number) than the STREAMS/UX scheduler; otherwise service routines will not run before the scheduler returns to user level from the kernel.

© 1995 Hewlett-Packard Development Company, L.P.