228 lines
6.0 KiB
C
228 lines
6.0 KiB
C
/* @(#)queue.h 1.1 94/10/31 Copyr 1987 Sun Micro */
|
|
/* Copyright (C) 1986. Sun Microsystems, Inc. */
|
|
|
|
#ifndef _lwp_queue_h
|
|
#define _lwp_queue_h
|
|
|
|
/*
|
|
* next-link (MUST BE FIRST in a structure) for singly-linked queues
|
|
* USAGE:
|
|
* struct foo {
|
|
* __queue_t next; (* MUST BE FIRST *)
|
|
* <other fields>;
|
|
* };
|
|
*/
|
|
typedef struct __queue_t {
|
|
struct __queue_t *q_next; /* hack since recursive typedefs not allowed */
|
|
} __queue_t;
|
|
#define QNULL ((__queue_t *) 0)
|
|
|
|
/* general queue header */
|
|
typedef struct qheader {
|
|
__queue_t hq_head; /* front of queue */
|
|
__queue_t hq_tail; /* back of queue */
|
|
} qheader_t;
|
|
#define QHNULL ((qheader_t *)0)
|
|
|
|
/* easy access to head and tail from a queue header */
|
|
#define q_head hq_head.q_next
|
|
#define q_tail hq_tail.q_next
|
|
|
|
/*
|
|
* All queue macros take pointers to qheaders to simplify
|
|
* using with register variables.
|
|
*/
|
|
|
|
/* initialize a queue */
|
|
#define INIT_QUEUE(q) {(q)->q_tail = (q)->q_head = QNULL; }
|
|
|
|
/* return first object in a queue */
|
|
#define FIRSTQ(q) ((q)->q_head)
|
|
|
|
/* true iff the queue is empty */
|
|
#define ISEMPTYQ(q) ((FIRSTQ(q) == QNULL) ? TRUE : FALSE)
|
|
|
|
/* insert an item at the end of a queue */
|
|
#define INS_QUEUE(queue, item) \
|
|
{ \
|
|
register qheader_t *q = queue; \
|
|
int __s; \
|
|
\
|
|
__s = splclock(); \
|
|
((__queue_t *)(item))->q_next = QNULL; \
|
|
if ((q)->q_head == QNULL) { \
|
|
(q)->q_head = (__queue_t *)(item); \
|
|
} else { \
|
|
(q)->q_tail->q_next = (__queue_t *)(item); \
|
|
} \
|
|
(q)->q_tail = (__queue_t *)(item); \
|
|
(void) splx(__s); \
|
|
}
|
|
|
|
/*
|
|
* Remove first item in a queue and return it in "val".
|
|
* The item returned in val should be of type "cast".
|
|
*/
|
|
#define REM_QUEUE(cast, queue, val) \
|
|
{ \
|
|
register __queue_t *front = FIRSTQ(queue); \
|
|
\
|
|
if ((front != QNULL) && (((queue)->q_head = front->q_next) == QNULL)) { \
|
|
(queue)->q_tail = QNULL; \
|
|
} \
|
|
val = cast front; \
|
|
}
|
|
|
|
/* same as REM_QUEUE but don't bother returning a value */
|
|
#define REMX_QUEUE(queue) \
|
|
{ \
|
|
register __queue_t *front = FIRSTQ(queue); \
|
|
\
|
|
if (front != QNULL) { \
|
|
if (((queue)->q_head = front->q_next) == QNULL) \
|
|
(queue)->q_tail = QNULL; \
|
|
front->q_next = QNULL; \
|
|
} \
|
|
}
|
|
|
|
/* Insert an item at the front of a queue (stack discipline) */
|
|
#define FRONT_QUEUE(q, item) \
|
|
{ \
|
|
if ((q)->q_head == QNULL) { \
|
|
(q)->q_tail = (__queue_t *)(item); \
|
|
} \
|
|
((__queue_t *)(item))->q_next = (q)->q_head; \
|
|
(q)->q_head = (__queue_t *)(item); \
|
|
}
|
|
|
|
/*
|
|
* Remove a particular element from a queue and return it
|
|
* in val with the appropriate cast.
|
|
*/
|
|
#define REM_ITEM(cast, queue, element, val) \
|
|
{ \
|
|
register __queue_t *q = FIRSTQ(queue); \
|
|
register __queue_t *prev = QNULL; \
|
|
int __s; \
|
|
\
|
|
__s = splclock(); \
|
|
while ((q != QNULL) && (q != (__queue_t *)(element))) { \
|
|
prev = q; \
|
|
q = q->q_next; \
|
|
} \
|
|
if (q != QNULL) { \
|
|
if (prev == QNULL) { \
|
|
(queue)->q_head = q->q_next; \
|
|
} else { \
|
|
prev->q_next = q->q_next; \
|
|
} \
|
|
if ((queue)->q_tail == q) \
|
|
(queue)->q_tail = prev; \
|
|
} \
|
|
val = cast q; \
|
|
(void) splx(__s); \
|
|
}
|
|
|
|
/* Same as REM_ITEM but don't bother returning the value */
|
|
#define REMX_ITEM(queue, element) \
|
|
{ \
|
|
register __queue_t *q = FIRSTQ(queue); \
|
|
register __queue_t *prev = QNULL; \
|
|
int rmq_ps; \
|
|
\
|
|
rmq_ps = splclock(); \
|
|
while ((q != QNULL) && (q != (__queue_t *)(element))) { \
|
|
prev = q; \
|
|
q = q->q_next; \
|
|
} \
|
|
if (q != QNULL) { \
|
|
if (prev == QNULL) { \
|
|
(queue)->q_head = q->q_next; \
|
|
} else { \
|
|
prev->q_next = q->q_next; \
|
|
} \
|
|
if ((queue)->q_tail == q) \
|
|
(queue)->q_tail = prev; \
|
|
} \
|
|
(void) splx(rmq_ps); \
|
|
}
|
|
|
|
/*
|
|
* Move the front of the queue to the back of the same queue.
|
|
* Return the NEW front value in val with the appropriate cast.
|
|
*/
|
|
#define BACK_QUEUE(cast, q, val) \
|
|
{ \
|
|
register __queue_t *front = FIRSTQ(q); \
|
|
\
|
|
if (front == QNULL) \
|
|
val = cast CHARNULL; \
|
|
else if (front->q_next == QNULL) \
|
|
val = cast front; \
|
|
else { \
|
|
(q)->q_head = front->q_next; \
|
|
front->q_next = QNULL; \
|
|
((q)->q_tail)->q_next = front; \
|
|
(q)->q_tail = front; \
|
|
val = cast (q)->q_head; \
|
|
} \
|
|
}
|
|
|
|
/*
|
|
* Same as BACK_QUEUE but no value returned. NB: No test for front == QNULL
|
|
* for speed since nobody (currently) relies on this.
|
|
*/
|
|
#define BACKX_QUEUE(q) \
|
|
{ \
|
|
register __queue_t *front = FIRSTQ(q); \
|
|
\
|
|
if (front->q_next != QNULL) { \
|
|
(q)->q_head = front->q_next; \
|
|
front->q_next = QNULL; \
|
|
((q)->q_tail)->q_next = front; \
|
|
(q)->q_tail = front; \
|
|
} \
|
|
}
|
|
|
|
/*
|
|
* insert proc in queue by priority (higher prio towards front).
|
|
*/
|
|
#define PRIO_QUEUE(queue, proc, curprio) \
|
|
{ \
|
|
register __queue_t *qu, *prevq; \
|
|
register int __s; \
|
|
\
|
|
__s = splclock(); \
|
|
for (prevq = QNULL, qu = (queue)->q_head; qu != QNULL; \
|
|
prevq = qu, qu = qu->q_next) { \
|
|
if ((curprio) > ((lwp_t *)qu)->lwp_prio) \
|
|
break; \
|
|
} \
|
|
((__queue_t *)(proc))->q_next = qu; \
|
|
if (prevq == QNULL) { \
|
|
(queue)->q_head = (__queue_t *)(proc); \
|
|
} else { \
|
|
prevq->q_next = (__queue_t *)(proc); \
|
|
} \
|
|
if (qu == QNULL) { \
|
|
(queue)->q_tail = (__queue_t *)(proc); \
|
|
} \
|
|
(void) splx(__s); \
|
|
}
|
|
|
|
/*
|
|
* Special identifying info for queued objects (lwp's and agents in particular).
|
|
* ALWAYS at offset 4 from the start of an object (immediately after
|
|
* the queueing field).
|
|
* To the client, an agent and a lwp are the same, but the nugget needs
|
|
* to know which is which.
|
|
*/
|
|
typedef enum object_type_t {
|
|
BADOBJECT_TYPE = 0, /* unintialized, thus a stale object */
|
|
PROCESS_TYPE = 1, /* lwp */
|
|
AGENT_TYPE = 2, /* agent */
|
|
} object_type_t;
|
|
#define TYPE(p) ((*(object_type_t *)((caddr_t)p + (sizeof (struct __queue_t)))))
|
|
|
|
#endif /* !_lwp_queue_h */
|