Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 May 1998 18:21:46 -0600
From:      "Justin T. Gibbs" <gibbs@plutotech.com>
To:        Julian Assange <proff@iq.org>
Cc:        gibbs@FreeBSD.ORG, hackers@FreeBSD.ORG, dyson@FreeBSD.ORG, mrg@eterna.com.au
Subject:   Re: more queue.h brokenness 
Message-ID:  <199805120025.SAA21481@pluto.plutotech.com>
In-Reply-To: Your message of "11 May 1998 22:22:31 -0000." <19980511222231.2857.qmail@iq.org> 

next in thread | previous in thread | raw e-mail | index | archive | help
>
>I notice someone (gibbs?) has updated sys/queue.h

For -stable?  Yes, it was me that brought currents sys/queue.h in.  The
changes that were made to sys/queue.h in this area, however, were 
performed by Kirk and are used by the soft update code.

>Unfortunately, because of the manner in which tqe_prev, and tqh_last
>are calculated, TAILQ_LAST and TAILQ_PREV need to be redefined like so:
>
>#define TAILQ_LAST(head) ((*((head)->tqh_last))? (*((head)->tqh_last)): TAILQ_
>FIRST(head))
>#define TAILQ_PREV(head, elm, field) (((elm) == TAILQ_FIRST(head))?NULL: *((el
>m)->field.tqe_prev))

This is unnecessary.  The original definitions are correct although 
perhaps not obviously so.  Let's look at the original definitions:

#define TAILQ_INIT(head) do {                                           \
        (head)->tqh_first = NULL;                                       \
        (head)->tqh_last = &(head)->tqh_first;                          \
} while (0)

#define TAILQ_PREV(elm, headname, field) \
        (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))

#define TAILQ_LAST(head, headname) \
        (*(((struct headname *)((head)->tqh_last))->tqh_last))

So, in the base case, after initialization, TAILQ_LAST returns exactly what
we would expect:
        (*(((struct headname *)((head)->tqh_last))->tqh_last))

as our tqh_last points to ourselves, this resolves to:

	(*(head)->tqh_last)

resolves to:

	head->tqh_first == NULL;

As the TAILQ macros will return to the initialized state after any number
of inserts or removals, the "empty" case works fine.

If the list has any elements in it, TAILQ_LAST also works correctly as 
we will look at either the tqe_next member of the element before the last,
or in the case of a single element list, our own tqh_first member.

The argument for TAILQ_PREV is much the same.  I'm sure that if you write
some code that makes use of these macros you will be able to convince 
yourself that they do work as desired.  One of the benefits of the new
TAILQ macros is that TAILQ_PREV gives you what you really want, a pointer 
to the real object, not your own previous double pointer.
	
>TAILQ_PREV is only used in vm/vm_object.c, which, presumably, is why
>no-one has noticed the problem before (and why I've cc'd dyson).

It's used in the soft update code as well as in latest version of the CAM
aic7xxx sequencer compiler.  Supporting CAM was the main reason I brought
the code in.

>Cheers,
>Julian.

--
Justin



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199805120025.SAA21481>