OpenSS7
SS7 for the
Common Man

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified:

Home Overview Status News Documentation Resources About
   
 Overview
 Status
 News
 Documentation
 Resources
 About

   
Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/drivers/queue.h


File /code/strss7/drivers/queue.h



#ifndef __QUEUE_H__
#define __QUEUE_H__

#define QR_DONE		0
#define QR_ABSORBED	1
#define QR_TRIMMED	2
#define QR_LOOP		3
#define QR_PASSALONG	4
#define QR_PASSFLOW	5
#define QR_DISABLE	6
#define QR_STRIP	7
#define QR_RETRY	8

/*
 *  -------------------------------------------------------------------------
 *
 *  M_FLUSH Handling
 *
 *  -------------------------------------------------------------------------
 */
STATIC INLINE int ss7_w_flush(queue_t *q, mblk_t *mp)
{
	if (*mp->b_rptr & FLUSHW) {
		if (*mp->b_rptr & FLUSHBAND)
			flushband(WR(q), mp->b_rptr[1], FLUSHALL);
		else
			flushq(WR(q), FLUSHALL);
		if (q->q_next)
			return (QR_PASSALONG);
		*mp->b_rptr &= ~FLUSHW;
	}
	if (*mp->b_rptr & FLUSHR) {
		if (*mp->b_rptr & FLUSHBAND)
			flushband(RD(q), mp->b_rptr[1], FLUSHALL);
		else
			flushq(RD(q), FLUSHALL);
		if (!q->q_next)
			return (QR_LOOP);
		*mp->b_rptr &= ~FLUSHR;
	}
	return (QR_DONE);
}
STATIC INLINE int ss7_r_flush(queue_t *q, mblk_t *mp)
{
	if (*mp->b_rptr & FLUSHR) {
		if (*mp->b_rptr & FLUSHBAND)
			flushband(RD(q), mp->b_rptr[1], FLUSHALL);
		else
			flushq(RD(q), FLUSHALL);
		if (q->q_next)
			return (QR_PASSALONG);
		*mp->b_rptr &= ~FLUSHR;
	}
	if (*mp->b_rptr & FLUSHW) {
		if (*mp->b_rptr & FLUSHBAND)
			flushband(WR(q), mp->b_rptr[1], FLUSHALL);
		else
			flushq(WR(q), FLUSHALL);
		if (!q->q_next)
			return (QR_LOOP);
		*mp->b_rptr &= ~FLUSHW;
	}
	return (QR_DONE);
}

/*
 *  =========================================================================
 *
 *  PUT and SRV
 *
 *  =========================================================================
 */

/*
 *  PUTQ Put Routine
 *  -------------------------------------------------------------------------
 */
STATIC INLINE int ss7_putq(queue_t *q, mblk_t *mp, int (*proc) (queue_t *, mblk_t *), void (*wakeup) (queue_t *))
{
	int rtn = 0;
	ensure(q, return (-EFAULT));
	ensure(mp, return (-EFAULT));
#if 0
	if (q->q_count || mp->b_datap->db_type < QPCTL) {
		putq(q, mp);
		return (0);
	}
#else
	if (q->q_count) {
		putq(q, mp);
		return (0);
	}
#endif
	if (ss7_trylockq(q)) {
		do {
			/* Fast Path */
			if ((rtn = proc(q, mp)) == QR_DONE) {
				freemsg(mp);
				break;
			}
			switch (rtn) {
			case QR_DONE:
				freemsg(mp);
			case QR_ABSORBED:
				break;
			case QR_STRIP:
				if (mp->b_cont)
					putq(q, mp->b_cont);
			case QR_TRIMMED:
				freeb(mp);
				break;
			case QR_LOOP:
				if (!q->q_next) {
					qreply(q, mp);
					break;
				}
			case QR_PASSALONG:
				if (q->q_next) {
					putnext(q, mp);
					break;
				}
				rtn = -EOPNOTSUPP;
			default:
				printd(("%s: %p: ERROR: (q dropping) %d\n", q->q_qinfo->qi_minfo->mi_idname,
					q->q_ptr, rtn));
				freemsg(mp);
				break;
			case QR_DISABLE:
				putq(q, mp);
				rtn = 0;
				break;
			case QR_PASSFLOW:
				if (mp->b_datap->db_type >= QPCTL || canputnext(q)) {
					putnext(q, mp);
					break;
				}
			case -ENOBUFS:
			case -EBUSY:
			case -ENOMEM:
			case -EAGAIN:
				putq(q, mp);
				break;
			case QR_RETRY:
				putq(q, mp);
				break;
			}
		} while (0);
		if (wakeup)
			wakeup(q);
		ss7_unlockq(q);
	} else {
		rare();
		putq(q, mp);
	}
	return (rtn);
}

/*
 *  SRVQ Service Routine
 *  -------------------------------------------------------------------------
 */
STATIC INLINE int ss7_srvq(queue_t *q, int (*proc) (queue_t *, mblk_t *), void (*wakeup) (queue_t *))
{
	int rtn = 0;
	ensure(q, return (-EFAULT));
	if (ss7_trylockq(q)) {
		mblk_t *mp;
		while ((mp = getq(q))) {
			/* Fast Path */
			if ((rtn = proc(q, mp)) == QR_DONE) {
				freemsg(mp);
				continue;
			}
			switch (rtn) {
			case QR_DONE:
				freemsg(mp);
			case QR_ABSORBED:
				continue;
			case QR_STRIP:
				if (mp->b_cont)
					putbq(q, mp->b_cont);
			case QR_TRIMMED:
				freeb(mp);
				continue;
			case QR_LOOP:
				if (!q->q_next) {
					qreply(q, mp);
					continue;
				}
			case QR_PASSALONG:
				if (q->q_next) {
					putnext(q, mp);
					continue;
				}
				rtn = -EOPNOTSUPP;
			default:
				printd(("%s: %p: ERROR: (q dropping) %d\n", q->q_qinfo->qi_minfo->mi_idname,
					q->q_ptr, rtn));
				freemsg(mp);
				continue;
			case QR_DISABLE:
				printd(("%s: %p: ERROR: (q disabling) %d\n", q->q_qinfo->qi_minfo->mi_idname,
					q->q_ptr, rtn));
				noenable(q);
				putbq(q, mp);
				rtn = 0;
				break;
			case QR_PASSFLOW:
				if (mp->b_datap->db_type >= QPCTL || canputnext(q)) {
					putnext(q, mp);
					continue;
				}
			case -ENOBUFS:	/* proc must have scheduled bufcall */
			case -EBUSY:	/* proc must have failed canput */
			case -ENOMEM:	/* proc must have scheduled bufcall */
			case -EAGAIN:	/* proc must re-enable on some event */
				if (mp->b_datap->db_type < QPCTL) {
					printd(("%s: %p: ERROR: (q stalled) %d\n",
						q->q_qinfo->qi_minfo->mi_idname, q->q_ptr, rtn));
					putbq(q, mp);
					break;
				}
				/* 
				 *  Be careful not to put a priority
				 *  message back on the queue.
				 */
				if (mp->b_datap->db_type == M_PCPROTO) {
					mp->b_datap->db_type = M_PROTO;
					mp->b_band = 255;
					putq(q, mp);
					break;
				}
				printd(("%s: %p: ERROR: (q dropping) %d\n", q->q_qinfo->qi_minfo->mi_idname,
					q->q_ptr, rtn));
				freemsg(mp);
				continue;
			case QR_RETRY:
				putbq(q, mp);
				continue;
			}
			break;
		}
		/* perform wakeups */
		if (wakeup)
			wakeup(q);
		ss7_unlockq(q);
	} else {
		rare();
	}
	return (rtn);
}

STATIC int ss7_oput(queue_t *q, mblk_t *mp)
{
	str_t *s = STR_PRIV(q);
	if (s->oq) {
		if (s->o_prim)
			ss7_putq(s->oq, mp, s->o_prim, s->o_wakeup);
		else
			putq(s->oq, mp);
	} else
		putq(q, mp);
	return (0);
}

STATIC int ss7_osrv(queue_t *q)
{
	str_t *s = STR_PRIV(q);
	if (s->oq) {
		if (s->o_prim) {
			ss7_srvq(s->oq, s->o_prim, s->o_wakeup);
			return (0);
		} else if (s->o_wakeup) {
			s->o_wakeup(s->oq);
			return (0);
		}
	}
	swerr();
	noenable(q);
	return (-EFAULT);
}

STATIC int ss7_iput(queue_t *q, mblk_t *mp)
{
	str_t *s = STR_PRIV(q);
	if (s->iq) {
		if (s->i_prim)
			ss7_putq(s->iq, mp, s->i_prim, s->i_wakeup);
		else
			putq(s->iq, mp);
	} else
		putq(q, mp);
	return (0);
}

STATIC int ss7_isrv(queue_t *q)
{
	str_t *s = STR_PRIV(q);
	if (s->iq) {
		if (s->i_prim) {
			ss7_srvq(s->iq, s->i_prim, s->i_wakeup);
			return (0);
		} else if (s->i_wakeup) {
			s->i_wakeup(s->iq);
			return (0);
		}
	}
	swerr();
	noenable(q);
	return (-EFAULT);
}

#endif				/* __QUEUE_H__ */


Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/drivers/queue.h

OpenSS7
SS7 for the
Common Man
Home Overview Status News Documentation Resources About

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified: