Page MenuHomeFreeBSD

bitset: Make BITSET big-endian friendly with compat32
AbandonedPublic

Authored by jhibbits on Wed, May 11, 8:54 PM.

Details

Reviewers
jhb
markj
kib
Summary

BITSET uses long as its basic underlying type, which is dependent on
the compile type, meaning on 32-bit builds the basic type is 32 bits,
but on 64-bit builds it's 64 bits. On little endian architectures this
doesn't matter, because the LSB is always at the low bit, so the words
get effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:

32-bit mode:

BIT_SET(foo, 0): 0x00000001

64-bit sees: 0x0000000100000000

Solve this by making this effectively a bit string, where all bits are
set linearly. In this case, we see it as follows:

BIT_SET(foo, 0): 0x80000000

64-bit sees: 0x8000000000000000

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint OK
Unit
No Unit Test Coverage
Build Status
Buildable 45535
Build 42423: arc lint + arc unit

Event Timeline

This breaks compatibility, right? i.e. big-endian programs compiled with the old bitset.h will not work. I'm not sure if it's an issue in practice.

Is anything other than cpuset(2) affected by the compat32 problem? Can we handle the problem in the freebsd32 layer instead?

sys/sys/bitset.h
205

Don't these macros need to be updated as well?

sys/vm/vm_phys.c
82

0x1L? Limbs of the bitset have type long, not unsigned long.

If the syscall bitset is limited to just cpuset, the syscall boundary would be better, yeah. I couldn't tell up front if it was limited to this, but on further inspection it looks like it is restricted to just cpuset, so I'll go that route instead.

sys/sys/bitset.h
205

You're right, this would need updated to use __BITNO(n).

sys/vm/vm_phys.c
82

Sure. I'm curious why it's long anyway, when it's a bit set, not an integer set.

If the syscall bitset is limited to just cpuset, the syscall boundary would be better, yeah. I couldn't tell up front if it was limited to this, but on further inspection it looks like it is restricted to just cpuset, so I'll go that route instead.

I believe cpuset_* is the only boundary where bitsets are used. There are signal masks as well, but they use a different implementation see _sigset.h. No conversion is needed there, I think.

Abandoning in favor of another way.