The circular list stuff was quite pretty but involved some really
unpleasant casting which modern GCC (quite properly) complains about
vociferously.
Replace it with more traditional doubly-linked-list hacking with
null-pointer sentinels, with the slightly nasty pointer swizzling tucked
away in useful macros. Some of the uses of these macros (e.g.,
unlinking the first or last item in a list) could be made more efficient
by using special-case versions, but it doesn't seem worthwhile.
static bres_server servers[BRES_MAX]; /* Statically allocated servers */
static bres_server servers[BRES_MAX]; /* Statically allocated servers */
-#define FREE ((bres_server *)&freelist)
-static struct { bres_server *next, *prev; } freelist = { FREE, FREE };
+static bres_server *freelist, *freetail;
+static bres_client *qhead, *qtail;
+static sel_state *sel;
+static const char *server = 0;
-#define QUEUE ((bres_client *)&queue)
-static struct { bres_client *next, *prev; } queue = { QUEUE, QUEUE };
+#define UNLINK(head, tail, p) do { \
+ *((p)->next ? &(p)->next->prev : &(tail)) = (p)->prev; \
+ *((p)->prev ? &(p)->prev->next : &(head)) = (p)->next; \
+} while (0)
+#define LINKHEAD(head, tail, p) do { \
+ (p)->next = (head); \
+ (p)->prev = 0; \
+ *((head) ? &(head)->prev : &(tail)) = (p); \
+ (head) = (p); \
+} while (0)
-static const char *server = 0;
+#define LINKTAIL(head, tail, p) do { \
+ (p)->next = 0; \
+ (p)->prev = (head); \
+ *((tail) ? &(tail)->next : &(head)) = (p); \
+ (tail) = (p); \
+} while (0)
/* --- Move the server to the back of the list --- */
/* --- Move the server to the back of the list --- */
- rs->next->prev = rs->prev;
- rs->prev->next = rs->next;
- rs->next = FREE;
- rs->prev = FREE->prev;
- FREE->prev->next = rs;
- FREE->prev = rs;
+ UNLINK(freelist, freetail, rs);
+ LINKTAIL(freelist, freetail, rs);
}
/* --- @bres_abort@ --- *
}
/* --- @bres_abort@ --- *
{
if (rc->q == BRES_BYNAME)
xfree(rc->u.name);
{
if (rc->q == BRES_BYNAME)
xfree(rc->u.name);
+ if (!rc->rs)
+ UNLINK(qhead, qtail, rc);
+ else {
sel_rmfile(&rc->rs->f);
zap(rc->rs);
rc->rs = 0;
sel_rmfile(&rc->rs->f);
zap(rc->rs);
rc->rs = 0;
- } else {
- rc->next->prev = rc->prev;
- rc->prev->next = rc->next;
- rs->next = FREE->next;
- rs->prev = FREE;
- FREE->next->prev = rs;
- FREE->next = rs;
+ LINKHEAD(freelist, freetail, rs);
/* --- Tie a timer onto the server block --- */
/* --- Tie a timer onto the server block --- */
/* --- If there are any clients waiting, attach one --- */
/* --- If there are any clients waiting, attach one --- */
- if (QUEUE->next != QUEUE) {
- rc = QUEUE->next;
- QUEUE->next = rc->next;
- rc->next->prev = QUEUE;
+ if (qhead) {
+ rc = qhead;
+ UNLINK(qhead, qtail, rc);
if (rs->kid != -1)
sel_rmtimer(&rs->t);
else {
if (rs->kid != -1)
sel_rmtimer(&rs->t);
else {
/* --- Fiddle with lists so that everything's OK --- */
sel_addfile(&rs->f);
/* --- Fiddle with lists so that everything's OK --- */
sel_addfile(&rs->f);
- rs->next->prev = FREE;
- FREE->next = rs->next;
- rs->next = rs->prev = rs;
+ UNLINK(freelist, freetail, rs);
rs->rc = rc;
rc->rs = rs;
return;
rs->rc = rc;
rc->rs = rs;
return;
/* --- If there's a free server, plug it in --- */
rc->rs = 0;
/* --- If there's a free server, plug it in --- */
rc->rs = 0;
- if (FREE->next == FREE) {
- rc->next = QUEUE;
- rc->prev = QUEUE->prev;
- QUEUE->prev->next = rc;
- QUEUE->prev = rc;
- } else
+ else
+ LINKTAIL(qhead, qtail, rc);
}
/* --- @bres_byaddr@ --- *
}
/* --- @bres_byaddr@ --- *
sel = s;
for (i = 0; i < BRES_MAX; i++) {
sel = s;
for (i = 0; i < BRES_MAX; i++) {
- servers[i].next = FREE;
- servers[i].prev = FREE->prev;
servers[i].kid = -1;
servers[i].rc = 0;
servers[i].kid = -1;
servers[i].rc = 0;
- FREE->prev->next = &servers[i];
- FREE->prev = &servers[i];
+ LINKTAIL(freelist, freetail, &servers[i]);