STREAMS-UX Programmer's Guide (February 2007)
Modules and Drivers
Design Guidelines
Chapter 4
84
Design Guidelines
Some of the common design guidelines for STREAMS modules and drivers have been explained here:
• STREAMS modules and drivers are not associated with any process and do not have a process or a user
context (except during open and close. Therefore modules and drivers cannot access the information from
the u_area of a process.
• Every STREAMS module and driver must process the M_FLUSH message according to the value of the
argument passed in the message.
• The contents of the data block (dblk_t) of a duped message, i.e., a message with the reference count
(db_ref) greater than one must not be changed by STREAMS drivers and modules.
• The modules and drivers should manipulate the queues and manage message buffers using the
STREAMS utilities provided in Appendix B, “STREAMS Utilities Supported by HP-UX.”
• The modules and drivers should refrain from imposing alignment or formatting rules on data in a M_DATA
message.
• A module or driver’s synchronization level determines the entities with which it can share data. The
synchronization level determines which queues a module or driver can pass to STREAMS utilities and
also the entities with which the modules and drivers can share the STREAMS queues.
For example, if a module uses queue pair synchronization, the write-side put procedure can call insq() to
insert a message onto the module’s read queue. But, if the module uses queue synchronization, the
write-side put procedure can only call insq() to insert messages onto the write queue.
In general, a put or service procedure can only pass its own queue or queues belonging to entities with
which it can share data. 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 procedure can call
putq if it passes a driver’s read queue or a lower mux’s write queue. However, putq’s caller must
guarantee that the queue passed in is still allocated.
Some STREAMS utilities, such as canput, are commonly passed a parameter of the form q->q_next.
These routines are restricted in a different way from those previously listed. A put or service procedure
can only pass its own queue’s q_next field or the q_next field of queues belonging to entities with which it
can share data. 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.
• Some restrictions exist for timeout and bufcall callback routines as well as non-streams code in the
kernel. This software cannot share data structures with STREAMS modules and drivers, unless spinlocks
are used to protect critical sections. Also, the code cannot call the following utilities: backq, bcanputnext,
canputnext, flushband, flushq, freezestr, getq, insq, putbq, putnext, putnextctl, putnextctl1,
putnextctl2, qreply, qsize, rmvq, SAMESTR, strqget, strqset, and unfreezestr.
Callback routines and non-streams code cannot call bcanput, canput, put, putctl, 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). Callback and non-streams code
can call putq or the streams_put utility only if they pass it a driver’s read queue or a lower mux’s write
queue.