Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 1 Aug 1996 13:47:35 +1000 (EST)
From:      David Leonard <leonard@dstc.edu.au>
To:        michaelh@cet.co.jp
Cc:        hackers@freebsd.org
Subject:   Re: kernel assertions (Rev. 1)
Message-ID:  <199608010347.NAA13864@foxtail.dstc.edu.au>

next in thread | raw e-mail | index | archive | help

> void
> bremfree(struct buf * bp)
> {
> 	int s = splbio();

> 	REQUIRE2(bp, "Expected bp to point to something")
> 	REQUIRE1(bp->b_qindex != QUEUE_NONE, "Expected a buffer on a
> queue");

> 	TAILQ_REMOVE(&bufqueues[bp->b_qindex], bp, b_freelist);
> 	bp->b_qindex = QUEUE_NONE;

> 	ENSURE2(bp->b_qindex == QUEUE_NONE, "Buffer should no longer be on
> a queue");

> 	splx(s);
> }

This might be a little arcane, but as you haven't yet talked about what
actual message is emitted, how about going the extra step in 
readable macros? something a little like this, maybe:

	REQUIRE("that bp points to something", bp != NULL);

	mod/file.c:123: require that bp points to something

and
	ENSURE( "that the buffer is no longer queued",
		bp->b_qindex == QUEUE_NONE );

	mod/file.c.124: Failed to ensure that the buffer is no longer queued
	


I really like the idea of names such as REQUIRE/ENSURE over ASSERT, but 
i hesitate at the numbers. 
But... one could get used to it I suppose. (sounds like a microsoft attitude) 



Looking at it again, I think it would raise the readability (and hence
learnability/searchability(?)) of the FreeBSD source tree no end! In some ways,
having to express the predicate that you are trying to ENSURE() essentially
documents your code better! Unless, of course you

	ENSURE( "bp!=NULL", bp!=NULL );

which I would like to see avoided :)



Other problems I can think of are:

- side effects of the conditionals
- conditions that take longer than constant time to be evaluated

So, sure you can whip up some simple-looking examples of ENSURE/REQUIRE, but
what about when you end up with something like this:

	ENSURE( "nothing in the queue has an invalid buffer",
		({ 
			thing* x;
			for(x=queue->head;x;x=x->next) 
				if ( !valid_buffer(x->buffer) ) return 0;
			return 1;
		}) );

first, valid_buffer() may have side effects which will alter operation
if these (expensive) checks are compiled out ,and second, being a linear 
time check, an interrupt or something may happen in the middle which might
affect the data structures being examined.

the long-time problem can be handled with ENSURE2, ENSURE3 and so on, but
does anyone have a nice way of handling the side-effect problem?

d
-- 
David Leonard                            Project Officer, DSTC
The University of Queensland             david.leonard@dstc.edu.au
http://www.dstc.edu.au/~leonard/



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