STREAMS Programming Guide

Exit Print View

Updated: July 2014
 
 

Lower Read put Procedure

The lower (linked) queue read put procedure is shown in the following example:

Example 13-6  Lower Read put Procedure
static int
muxlrput(queue_t *q, mblk_t *mp)
{
	queue_t *uq;
	int device;

	if(muxerr) {
			freemsg(mp);
			return (0);
	}

	switch(mp->b_datap->db_type) {
	case M_FLUSH:
			/*
			 * Flush queues. NOTE: sense of tests is reversed
			 * since we are acting like a "stream head"
			 */
			if (*mp->b_rptr & FLUSHW) {
				*mp->b_rptr &= ~FLUSHR;
				qreply(q, mp);
			} else
				freemsg(mp);
			break;
	case M_ERROR:
	case M_HANGUP:
			muxerr = 1;
			freemsg(mp);
			break;
	case M_DATA:
			/*
			 * Route message. First byte indicates
			 * device to send to. No flow control.
			 *
			 * Extract and delete device number. If the
			 * leading block is now empty and more blocks
			 * follow, strip the leading block.
			 */
			device = *mp->b_rptr++;

			/* Sanity check. Device must be in range */
			if (device < 0 || device >= mux_cnt) {
				freemsg(mp);
				break;
			}
			/*
			 * If upper stream is open and not backed up,
			 * send the message there, otherwise discard it.
			 */
			uq = mux_mux[device].qptr;
			if (uq != NULL && canputnext(uq))
				putnext(uq, mp);
			else
				freemsg(mp);
			break;
	default:
			freemsg(mp);
	}
	return (0);
}

muxlrput receives messages from the linked stream. In this case, it is acting as a stream head and handles M_FLUSH messages. The code is the reverse of a driver, handling M_FLUSH messages from upstream. There is no need to flush the read queue because no data is ever placed in it.

muxlrput also handles M_ERROR and M_HANGUP messages. If one is received, it locks up the upper streams by setting muxerr.

M_DATA messages are routed by checking the first data byte of the message. This byte contains the minor device of the upper stream. Several checks examine whether:

  • The device is in range

  • The upper stream is open

  • The upper stream is full

This multiplexer does not support flow control on the read side; it is merely a router. If the message passes all checks, it is put to the proper upper queue. Otherwise, the message is discarded.

The upper stream close routine clears the mux entry so this queue will no longer be found. Outstanding bufcalls are not cleared.

/*
* Upper queue close
*/
static int
muxclose(queue_t *q, int flag, cred_t *credp)
{
	struct mux *mux;

	mux = (struct mux *) q->q_ptr;
	qprocsoff(q);
	if (mux->bufcid != 0)
		unbufcall(mux->bufcid);
	mux->bufcid = 0;
	mux->ptr = NULL;
	q->q_ptr = NULL;
	WR(q)->q_ptr = NULL;
	return(0);
}