Re: Bogus sparse warning?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 13 Feb 2007, at 00:42, Linus Torvalds wrote:
On Tue, 13 Feb 2007, Anton Altaparmakov wrote:
I have Christopher Li's patch applied and with that and changing to the
(*get_block_t) in linux/fs.h it now produces no warnings:

I suspect that even without Chris' patch, you wouldn't get a warning with
the explicit "pointer" conversion in <linux/fs.h>. But I didn't test.

I did't either. The good news is that Chris' second patch fixes the warning both with the explicit "pointer" conversion and without.

I then pulled the new sparse repository and changed from -Wbitwise to
-D__CHECK_ENDIAN__ and then got tons of warnings that did not use to be
there before.  I managed to fix all except the two I reported on the
mailing list yesterday (and one more that I have not looked at yet - in
fs/ntfs/runlist.c I get 18 warnings like this:

fs/ntfs/runlist.c:1549:18: warning: potentially expensive pointer subtraction

Ok. That happens for code like

	struct some_struct *p, *q;
	int i;

	i = p - q;

because not everybody realizes that this simple subtraction can actually
generate tons of instructions. It basically becomes

	i = ((unsigned long)p - (unsigned long)q) / sizeof(some_struct);

which is a potentially 64-bit divide with an awkward (but constant)
divisor.

If the sizeof is a power-of-two, we don't care, because then it's
obviously a normal shift. But depending on compiler and architecture and exact size of the struct, it can actually be tens of instructions and lots
of cycles (gcc often tries to turn divisions by constants into a fancy
code-sequence, which explains the "tens of instructions" part).

So the "potentially expensive" warning is not something really bad, but it
can be a sign of "maybe you didn't realize that this can be quite
expensive".

We had some code-sequences in the kernel where we could just rewrite the
subtraction to something else entirely, and get rid of code.

Yes you are quite right in what it is flagging up. But I would have assumed that my current code is more efficient than alternatives. Here is the code from the first warning:

                /* Determine the runlist size. */
                trl = rl + 1;
                while (likely(trl->length))
                        trl++;
                old_size = trl - runlist->rl + 1;

Note "rl" and "trl" are "structs" of size 24 bytes (i.e. not a power of 2). What we are dealing with here is an array of those "structs" which is terminated by a "struct" where its "->length" is zero. And I do the above loop to get the size, i.e. I look for the last element and then subtract the first element from the last element and add one to get the number of elements in the array.

Is this not more efficient than say doing it using an index like so:

	for (old_size = 0; rl[old_size].length; old_size++)
		;
	old_size++;

My assumption has always been that using the rl[index] would generate larger and slower instructions because of the non-constant offset from pointer base.

Have I been going wrong all those years and in fact that is better? Or is there yet another way of doing the above more efficiently?

(Yes I know that keeping the size of the array in the array header would be most efficient but that is not how the code works at the moment. It is my long term goal to switch to code that does make use of the array size and in fact in my OSX NTFS driver I have done this and plan to backport the changes to the Linux driver once I have it working there...)

Best regards,

	Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer, http://www.linux-ntfs.org/


-
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux