Subject: Re: Bitfields and kernel
To: None <tech-kern@netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: tech-kern
Date: 09/30/1999 16:38:28
>>> reg_msr_t msr;
>>> msr.pow = 1;
>>> msr.ile = 0;
>> The biggest problem with this, aside from the nonportability various
>> people have commented on, is that it becomes impossible to
>> manipulate multiple bits at the same time. This can be important
>> for setting and clearing bits and can be useful when testing bits.
> For setting multiple bits, using bitfields will work, and gcc
> optimizes it as tight as any hand-coded or (1<<30)|(1<<25) code
Not if the variable is volatile - or rather, if it does in that case
then it's broken. (Granted, this matters comparatively seldom.)
Also, your claim is false on the SPARC, at least in a small test I just
did.
struct foo {
unsigned int a : 1;
unsigned int b : 1;
unsigned int c : 1;
} ;
struct foo *fp;
void setfoo(void);
void setfoo(void)
{
fp->a = 1;
fp->b = 1;
}
Using -S -O99, I got assembly code the core of which was
ld [%o0],%g2
sethi %hi(-2147483648),%g3
or %g2,%g3,%g2
sethi %hi(1073741824),%g3
or %g2,%g3,%g2
retl
st %g2,[%o0]
where there's no reason at all not to do a single sethi and or. (This
was with gcc 2.7.2.2. "Modern" gcc, egcs-1.1.2 it calls itself, does
even worse, doing one ld-modify-st per source-code assignment even with
-O99 and no "volatile".)
> For testing multiple bits, to me it is more clear to say
> if ((msr.pow == 1) && (msr.ile == 0))
> than
> if ((msr&POW_BIT) && !(msr&ILE_BIT))
> or
> if ((msr&POW_BIT == POW_BIT) && (msr&ILE_BIT == 0))
But what you should be comparing to is
if ((msr & (POW_BIT|ILE_BIT)) == POW_BIT)
which reads msr only once (semantically significant if msr is volatile
and possibly worth paying attention to as an optimization if it's a
complicated expression).
> It looks like there's no clear consensus :),
Sure does look that way. Especially since some important aspects vary,
it appears, from architecture to architecture.
der Mouse
mouse@rodents.montreal.qc.ca
7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B