Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
8.  STREAMS Kernel-Level Mechanisms General ioctl Processing Transparent ioctl Examples I_LIST ioctl(2)Example  Previous   Contents   Next 
   
 

M_FLUSH Message Handling

All modules and drivers are expected to handle M_FLUSH messages. An M_FLUSH message can originate at the stream head or from a module or a driver. The user can cause data to be flushed from queued messages of a stream by submiting an I_FLUSH ioctl(2). Data can be flushed from the read side, write side, or both sides of a stream.

ioctl(fd,I_FLUSH, arg);

The first byte of the M_FLUSH message is an option flag. The following table describes the possible values for this flag.

Table 8-1 M_FLUSH Arguments and bi_flag Values

Flag

Description

FLUSHR

Flush read side of stream

FLUSHW

Flush write queue

FLUSHRW

Flush both, read and write, queues

FLUSHBAND

Flush a specified priority band only

Flushing According to Priority Bands

In addition to being able to flush all the data from a queue, a specific band can be flushed using the I_FLUSHBAND ioctl(2).

ioctl(fd, I_FLUSHBAND, bandp); 

The ioctl(2) is passed a pointer to a bandinfo structure. The bi_pri field indicates the band priority to be flushed (from 0 to 255). The bi_flag field indicates the type of flushing to be done. The legal values for bi_flag are defined in Table 8-1. bandinfo has the following format:

struct bandinfo {
		unsigned char       bi_pri;
		in                  bi_flag;
};

See "M_FLUSH" for details on how modules and drivers should handle flush band requests.

Figure 8-1 and Figure 8-2 further demonstrate flushing the entire stream due to a line break. Figure 8-1 shows the flushing of the write side of a stream, and Figure 8-2 shows the flushing of the read side of a stream.

Figure 8-1 Flushing the Write Side of a Stream

The following discussion describes the sequence of events shown in Figure 8-1 (dotted lines mean flushed queues):

  1. A break is detected by a driver.

  2. The driver generates an M_BREAK message and sends it upstream.

  3. The module translates the M_BREAK into an M_FLUSH message with FLUSHW set, then sends it upstream.

  4. The stream head does not flush the write queue (no messages are ever queued there).

  5. The stream head turns the message around (sends it down the write side).

  6. The module flushes its write queue.

  7. The message is passed downstream.

  8. The driver flushes its write queue and frees the message.

Figure 8-2 shows flushing the read side of a stream.

Figure 8-2 Flushing the Read Side of a Stream

The following discussion describes the sequence of events.

  1. After generating the first M_FLUSH message, the module generates an M_FLUSH with FLUSHR set and sends it downstream.

  2. The driver flushes its read queue.

  3. The driver turns the message around (sends it up the read side).

  4. The module flushes its read queue.

  5. The message is passed upstream.

  6. The stream head flushes the read queue and frees the message.

The following code shows line discipline module for flush handling.


Example 8-14 Line Discipline Module for Flush Handling

static int
ld_put(
 	queue_t *q,					/* pointer to read/write queue */
 	mblk_t *mp)					/* pointer to message being passed */
{
 	switch (mp->b_datap->db_type) {
 		default:
 			putq(q, mp); /* queue everything */
			return (0);					 /* except flush */

 		case M_FLUSH:
 			if (*mp->b_rptr & FLUSHW)				  /* flush write q */
 					flushq(WR(q), FLUSHDATA);

 			if (*mp->b_rptr & FLUSHR)				  /* flush read q */
 					flushq(RD(q), FLUSHDATA);

 			putnext(q, mp);							  /* pass it on */
 			return(0);
 	}
}

The above example uses FLUSHDATA as the argument to flushq. This code will flush data type messages (M_DATA, M_DELAY, M_PROTO and M_PCPROTO) only. Flushing non-data messages, such as M_IOCTL, M_IOCACK, and M_IOCNAK, might flush messages that contain critical state in the stream. If an M_IOCACK message is flushed, a thread waiting at the stream head for a non-data message response will never receive it. Care should be taken when using flushq.

The stream head turns around the M_FLUSH message if FLUSHW is set (FLUSHR is cleared). A driver turns around M_FLUSH if FLUSHR is set (should mask off FLUSHW).

Flushing Priority Band

The bi_flag field is one of FLUSHR, FLUSHW, or FLUSHRW.

The following example shows flushing according to the priority band.


Example 8-15 Priority Band Data Flush Handling

queue_t *rdq;								/* read queue */
queue_t *wrq;								/* write queue */

	case M_FLUSH:
		if (*bp->b_rptr & FLUSHBAND) {
			if (*bp->b_rptr & FLUSHW)
				flushband(wrq, FLUSHDATA, *(bp->b_rptr + 1));
			if (*bp->b_rptr & FLUSHR)
				flushband(rdq, FLUSHDATA, *(bp->b_rptr + 1));
		} else {
			if (*bp->b_rptr & FLUSHW)
				flushq(wrq, FLUSHDATA);
			if (*bp->b_rptr & FLUSHR)
				flushq(rdq, FLUSHDATA);
		}
		/*
		 * modules pass the message on;
		 * drivers shut off FLUSHW and loop the message
		 * up the read-side if FLUSHR is set; otherwise,
		 * drivers free the message.
		 */
		break;

 
 
 
  Previous   Contents   Next