STREAMS Programming Guide

close Routine

The close routine of devices is called only during the last close of the device. Module close routines are called during the last close or if the module is popped.

The prototype for the close entry point is:


int prefix_close (queue *q, int flag, cred_t * cred_p)
q

is a pointer to the read queue of the module.

flag

is analogous to the oflag parameter of the open entry point. If FNBLOCK or FNDELAY is set, then the module should attempt to avoid blocking during the close.

cred_p

is a pointer to the user credential structure.

Like open, the close entry point has user context and can block. Likewise, the blocking routines should return in the event of a signal. Device drivers must take into consideration that interrupts are not blocked during close. The close routine must cancel all pending and qbufcall callbacks, and process any remaining messages on its service queue.

The open and close procedures are only used on the read side of the queue and can be set to NULL in the write-side qinit structure initialization. Example 7–2 shows an example of a module close routine.


Example 7–2 Example of a Module Close

/* example of a module close */
static int
xx_close(queue_t *, *rq, int flag, cred_t *credp)
{
		struct xxstr   *xxp;
  
   /*
    * Disable xxput() and xxsrv() procedures on this queue.
    */
		qprocsoff(rq);
		xxp = (struct xxstr *) rq->q_ptr;

   /*
    * Cancel any pending timeout.
    * This example assumes that the timeout was issued
    * against the write queue.
    */

		if (xxp->xx_timeoutid != 0) {
			(void) quntimeout(WR(rq), xxp->xx_timeoutid);
			xxp->xx_timeoutid=0;
    }
   /*
    * Cancel any pending bufcalls.
    * This example assumes that the bufcall was issued
    * against the write queue.
    */
		if (xxp->xx_bufcallid !=0) {
			(void) qunbufcall(WR(rq), xxp->xx_bufcallid);
 		xxp->xx_bufcallid = 0;
		}
		rq->q_ptr = WR(rq)->q_ptr = NULL;

   /*
    * Free resources allocated during open
    */
		kmem_free (xxp, sizeof (struct xxstr));
		return (0);
}

qprocsoff does the inverse operation shown in Figure 7–9. This supports the need for cancelling callbacks before a qprocsoff.

qprocsoff is typically called at the begining of the close routine. The module can no longer receive messages from adjoining modules. The queue, however, still has pointers to it's adjoining modules and can putnext. However, as the queue is no longer inserted into the stream, these messages may be out of order from other messages in the stream, so it is best to process these messages before qprocsoff.

qwait is used because a module needs to get some response from another module or driver in the STREAM (i.e. a DLPI disconnect message sent downstream). qwait and qwait_sig must also be called before qprocsoff because once the queue is removed from the stream, there will be no way for the reply message to reach the queue.