149 lines
3.8 KiB
C
149 lines
3.8 KiB
C
#ifndef _Q_H_
|
|
#define _Q_H_
|
|
|
|
/**************************************************************************
|
|
* *
|
|
* Copyright (C) 1996 Silicon Graphics, Inc. *
|
|
* *
|
|
* These coded instructions, statements, and computer programs contain *
|
|
* unpublished proprietary information of Silicon Graphics, Inc., and *
|
|
* are protected by Federal copyright law. They may not be disclosed *
|
|
* to third parties or copied or duplicated in any form, in whole or *
|
|
* in part, without the prior written consent of Silicon Graphics, Inc. *
|
|
* *
|
|
**************************************************************************/
|
|
|
|
#include "common.h"
|
|
|
|
#define Q_DECLARE(que) q_t que = { &que, &que }
|
|
#define Q_INIT(que) ((que)->next = (que)->prev = que)
|
|
|
|
#define Q_HEAD(que, typ) Q_NEXT(que, typ)
|
|
#define Q_NEXT(que, typ) ((typ)(((q_t *)(que))->next))
|
|
#define Q_TAIL(que) ((que)->prev)
|
|
#define Q_END(que, elt) ((que) == (q_t *)(elt))
|
|
|
|
#define Q_EMPTY(que) ((que)->next == (que))
|
|
|
|
#define Q_ADD_FIRST(que, elt) \
|
|
MACRO_BEGIN \
|
|
((q_t *)(elt))->next = (que)->next; \
|
|
((q_t *)(elt))->prev = (que); \
|
|
(que)->next->prev = (q_t *)(elt); \
|
|
(que)->next = (q_t *)(elt); \
|
|
MACRO_END
|
|
|
|
#define Q_ADD_LAST(que, elt) \
|
|
MACRO_BEGIN \
|
|
((q_t *)(elt))->next = (que); \
|
|
((q_t *)(elt))->prev = (que)->prev; \
|
|
(que)->prev->next = (q_t *)(elt); \
|
|
(que)->prev = (q_t *)(elt); \
|
|
MACRO_END
|
|
|
|
#define Q_REM_FIRST(que, elt, typ) \
|
|
MACRO_BEGIN \
|
|
if ((que)->next == (que)) { \
|
|
(elt) = 0; \
|
|
} else { \
|
|
(elt) = (typ)((que)->next); \
|
|
(que)->next = (que)->next->next; \
|
|
(que)->next->prev = (que); \
|
|
} \
|
|
MACRO_END
|
|
|
|
#define Q_UNLINK(elt) \
|
|
MACRO_BEGIN \
|
|
q_t *_q = (q_t *)(elt); \
|
|
_q->next->prev = _q->prev; \
|
|
_q->prev->next = _q->next; \
|
|
MACRO_END
|
|
|
|
#define Q_INSERT_TAIL(que, elt, type, fld) \
|
|
MACRO_BEGIN \
|
|
q_t *_prev; \
|
|
\
|
|
for (_prev = (que)->prev; \
|
|
_prev != (que) && ((type*)_prev)->fld < (elt)->fld;\
|
|
_prev = _prev->prev) { \
|
|
} \
|
|
Q_ADD_FIRST(_prev, elt); \
|
|
MACRO_END
|
|
|
|
#define Q_INSERT_HEAD(que, elt, type, fld) \
|
|
MACRO_BEGIN \
|
|
q_t *_next; \
|
|
\
|
|
for (_next = (que)->next; \
|
|
_next != (que) && ((type*)_next)->fld > (elt)->fld;\
|
|
_next = _next->next) { \
|
|
} \
|
|
Q_ADD_LAST(_next, elt); \
|
|
MACRO_END
|
|
|
|
#define Q_PRINT(que) do { \
|
|
MACRO_BEGIN \
|
|
q_t *_q = (&(que))->next; \
|
|
dbg_printf("%s:\n", #que); \
|
|
dbg_printf("\t0x%x: 0x%x, 0x%x\n", \
|
|
&que, (&(que))->next, (&(que))->prev); \
|
|
while (_q != &(que)) { \
|
|
dbg_printf("\t0x%x: 0x%x, 0x%x\n", \
|
|
_q, _q->next, _q->prev); \
|
|
_q = _q->next; \
|
|
} \
|
|
MACRO_END
|
|
|
|
|
|
typedef struct q {
|
|
struct q *next;
|
|
struct q *prev;
|
|
} q_t;
|
|
|
|
|
|
|
|
/* Singly linked queues.
|
|
*
|
|
* These lists do not require locks but should be only used when
|
|
* the caller cannot be preempted as they spin to resolve collisions.
|
|
*/
|
|
#define QS_DECLARE(qs) qs_t * volatile qs
|
|
#define QS_INIT(que) (*(que) = 0)
|
|
|
|
#define QS_BUSY ((qs_t *)1uL)
|
|
|
|
#define QS_ADD_FIRST(head, elt) \
|
|
MACRO_BEGIN \
|
|
ASSERT(sched_entered()); \
|
|
for (;;) { \
|
|
((qs_t *)(elt))->qs_next = *(head); \
|
|
if (((qs_t *)(elt))->qs_next != QS_BUSY \
|
|
&& cmp_and_swap((void *)head, \
|
|
((qs_t *)(elt))->qs_next, elt)) { \
|
|
break; \
|
|
} \
|
|
} \
|
|
MACRO_END
|
|
|
|
#define QS_REM_FIRST(head, elt, typ) \
|
|
MACRO_BEGIN \
|
|
ASSERT(sched_entered()); \
|
|
for (;;) { \
|
|
if (!(elt = (typ)*(head))) { \
|
|
break; \
|
|
} \
|
|
if (elt != (typ)QS_BUSY \
|
|
&& cmp_and_swap((void *)head, elt, QS_BUSY)) { \
|
|
*(head) = ((qs_t *)(elt))->qs_next; \
|
|
break; \
|
|
} \
|
|
} \
|
|
MACRO_END
|
|
|
|
typedef struct qs {
|
|
struct qs *qs_next;
|
|
} qs_t;
|
|
|
|
|
|
#endif /* !_Q_H_ */
|