h58210
s 00315/00000/00000
d D 3.1 84/11/13 16:29:11 dan 1 0
c date and time created 84/11/13 16:29:11 by dan
e
u
U
t
T
I 1
/*  qsubs.c -- Queue management subroutines
 *  copyright (c)
 *	Daniel Steinberg
 *	October, 1983
 *
 */

#include "viosconf.h"
#include "handlers.h"
#include "iopacket.h"
#include "pktfuncs.h"


    int **
q_item (item, que)
    register LIST_HEAD **item;
    register LIST_HEAD *que;

/* q_item (item, que) -- Add an item to the back of a doubly-linked queue
 *
 *	in:	item		bufptr to item to queue
 *	mod:	que		address of queue listhead
 *	return:	(int **)	bufptr to the item queued
 *	thrown:	(NONE)
 *
 *	Add an item to the back a doubly-linked, presumably FIFO, queue.
 *
 *	Maintains the following linkage conventions:
 *
 *	LIST_HEAD Next----+------>1st ITEM Next------------
 *	LIST_HEAD Last-   ^       1st ITEM Last--NULL     |
 *	              |   |                               |
 *	              |   |  ------------------------------
 *	              |   |  |
 *	              |   |  --+->2nd ITEM Next------------
 *	              |   |    ^  2nd ITEM Last---        |
 *	              |   |    ^                 |        |
 *	              |   -----^------------------        |
 *	              |        ^                          |
 *	              |        ^                          |
 *	              |
 *	              |    <<<<<<<<<<  etc  >>>>>>>>>>
 *	              |
 *	              |        ^                          |
 *	              |        ^                          |
 *	              |        ^  -------------------------
 *	              |        ^  |
 *	              ---------^--+-->last ITEM Next--NULL
 *	                       ^      last ITEM Last---
 *	                       |                      |
 *	                       ------------------------
 */
{
    register LIST_HEAD **ptr;		/* temporary storage */

    if (item EQ NULL) return(NULL);	/* NULL items are allowed */

    DIS_INTS;

    /* link end of queue to new item and point to it */
    if ( (Last(*item) = ptr = Last(que)) NE NULL )  Next(*ptr) = item;
    /* link new item to end of queue */
    Next(*(Last(que) = item)) = NULL;

    if (Next(que) EQ NULL)  Next(que) = item;	/* queue was empty */

    ENA_INTS;

    return((int**)item);
}

    int **
pq_item (item, que)
    register LIST_HEAD **item;
    LIST_HEAD *que;

/* pq_item (item, que) -- Add item to a priority-ordered, doubly-linked queue
 *
 *	in:	item		bufptr to item to queue
 *	mod:	que		address of queue listhead
 *	return:	(int **)	bufptr to the item queued
 *	thrown:	(NONE)
 *
 *	Add an item into a doubly-linked, priority-ordered, queue.
 *	New items are queued after items of equal priority so that the
 *	queue, if dequeued from the front, is FIFO for each priority.
 *
 *	Priority is taken from the Priority offset of an i/o packet.
 *	Therefore, if 'item' is not an i/o packet, it had better have its
 *	priority in the same location and format.
 *
 *	Queue format is the same as documented for q_item() (above).
 *	Highest priority items are first in the queue.
 */
{
    register LIST_HEAD **ptr;		/* next item */
    register LIST_HEAD **optr;		/* previous item */
    PKT_PRIORITY pri;			/* item priority */

    if (item EQ NULL) return(NULL);	/* NULL items are allowed */
    pri = Priority(*(PKT_PTR)item);	/* get this item priority */

    DIS_INTS;

    /* find appropriate place in queue (link after items of same priority) */
    optr = NULL;
    ptr = Next(que);		/* start at front and look down */
    while (ptr NE NULL)
	{
	if (Priority(*(PKT_PTR)ptr) LT pri)  break;	/* insert before ptr */
	optr = ptr;				/* save old ptr */
	ptr = Next(*ptr);			/* point to next item */
	}

    /* link item after optr and before ptr */
    if ( (Next(*item) = ptr) NE NULL )  Last(*ptr) = item;
    else  Last(que) = item;
    if ( (Last(*item) = optr) NE NULL )  Next(*optr)= item;
    else  Next(que) = item;

    ENA_INTS;
    return((int**)item);
}

    int **
dq_item (que)
    register LIST_HEAD *que;

/* dq_item (que) -- Dequeue an item from the head of a doubly-linked queue
 *
 *	mod:	que		queue listhead
 *	return:	(int **)	bufptr to the item dequeued
 *	thrown:	(NONE)
 *
 *	The first item in the queue whose listhead is 'que' is dequeued.
 *
 *	Uses u_q_item() to do the actual queue removal.
 */
{
    register LIST_HEAD **ptr;

    DIS_INTS;

    ptr = Next(que);
    if (ptr NE NULL)
	u_q_item(ptr,que);	/* unlink first item, if any */

    ENA_INTS;

    return((int**)ptr);
}

    int **
uq_item (item ,que)
    register LIST_HEAD **item;
    register LIST_HEAD *que;

/* uq_item (item, que) -- Unlink an item from a doubly-linked queue
 *
 *	in:	item		item to dequeue
 *	mod:	que		queue listhead
 *	return:	(int **)	bufptr to the item dequeued
 *	thrown:	(NONE)
 *
 *	The given item is removed from the queue whose listhead is 'que'.
 *
 *	If 'item' is not actually linked into the queue, the database
 *	will be corrupted!
 *
 *	Uses u_q_item() to do the actual queue removal.
 */
{
    DIS_INTS;

    u_q_item(item,que);

    ENA_INTS;

    return((int**)item);
}

    int**
u_q_item (item ,que)
    register LIST_HEAD **item;
    register LIST_HEAD *que;

/* u_q_item (item, que) -- Unlink an item from a doubly-linked queue
 *
 *	in:	item		item to dequeue
 *	mod:	que		queue listhead
 *	return:	(int**)		bufptr to item dequeued
 *	thrown:	(NONE)
 *
 *	The given item is removed from the queue whose listhead is 'que'.
 *
 *	If 'item' is not actually linked into the queue, the database
 *	will be corrupted!
 */
{
    register LIST_HEAD  **ptr;	/* next item */
    register LIST_HEAD **optr;	/* previous item */

    optr = Last(*item);
    if ((ptr=Next(*item)) NE NULL)  Last(*ptr) = optr;
    else  Last(que) = optr;

    if (optr NE NULL)  Next(*optr) = ptr;
    else  Next(que) = ptr;

    return((int**)item);
}


q_activate (cnd, limit, dev, que)
    register PKT_STATE cnd;
    int limit;
    register PDD_PTR dev;
    register LIST_HEAD *que;

/* q_activate (cnd, limit, dev, que) -- Search for i/o packet(s) to activate
 *
 *	in:	cnd		Target packet state
 *	in:	limit		Number of pkts to activate;  zero, if no limit
 *	in:	dev		Target device;  NULL, if match all devices
 *	mod:	que		Target wait queue
 *	return:	(NONE)
 *	thrown:	(NONE)
 *
 *	Search an i/o packet wait queue, specified by 'que',
 *	for one or more packets (up to 'limit') that meet the following
 *	conditions:
 *		1) The current state of the packet matches 'cnd'.
 *		2) If 'dev' is not NULL, the target device of the packet
 *		   matches 'dev'.
 *
 *	If any packets meet the above criteria, activate them by removing
 *	them from 'que' and adding them to the back of Vqueue with their
 *	state set to VIO_RUN_STATE.
 *
 */
{
    register PKT_PTR pkt;	/* packet to test */
    register PKT_PTR nptr;	/* packet after 'pkt', (requeuing loses link) */

    DIS_INTS;

    pkt = (PKT_PTR) Next(que);	/* Point to first item in queue */

    while (pkt NE NULL)		/* Loop through entire queue (maybe) */
	{
	nptr = Next(*pkt);	/* Save ptr to next packet in queue */

	if ( (State(*pkt) EQ cnd) AND
		( (dev EQ NULL) OR (PDevice(*pkt) EQ dev) ) )
	    {
	    State(*pkt) = VIO_RUN_STATE;	/* activate this packet */
	    q_virtual(u_q_item(pkt, que));	/* switch queues */
	    if (--limit EQ 0)  break;		/* quit if limit reached */
	    }

	pkt = nptr;		/* Try next packet in queue */
	}

    ENA_INTS;
    vio_reschedule();		/* Be sure and check queues before quitting */
}

    PKT_PTR
q_locate (cnd, dev, que)
    register PKT_STATE cnd;
    register PDD_PTR dev;
    register LIST_HEAD *que;

/* q_locate (cnd, dev, que) -- Search for an i/o packet with matching condition
 *
 *	in:	cnd		Target packet state
 *	in:	dev		Target device;  NULL, if match all devices
 *	mod:	que		Target wait queue listhead address
 *	return:	(PKT_PTR)	Appropriate I/O packet ptr or NULL
 *	thrown:	(NONE)
 *
 *	Search an i/o packet wait queue, specified by 'que',
 *	for one packet that meets the following conditions:
 *		1) The current state of the packet matches 'cnd'.
 *		2) If 'dev' is not NULL, the target device of the packet
 *		   matches 'dev'.
 *
 *	If a packet meets the above criteria, return its address.
 *
 */
{
    register PKT_PTR pkt;	/* packet to test */
    register PKT_PTR nptr;	/* packet after 'pkt', (requeuing loses link) */

    DIS_INTS;

    pkt = (PKT_PTR) Next(que);	/* Point to first item in queue */

    while (pkt NE NULL)		/* Loop through entire queue (maybe) */
	{
	nptr = Next(*pkt);	/* Save ptr to next packet in queue */

	if ( (State(*pkt) EQ cnd) AND
		( (dev EQ NULL) OR (PDevice(*pkt) EQ dev) ) )
	    {
	    break;		/* quit if packet match found */
	    }

	pkt = nptr;		/* Try next packet in queue */
	}

    ENA_INTS;

    return(pkt);		/* return the valid packet ptr or NULL */
}
E 1
