With INVARIANTS defined, have the functions that check address alignment and boundaries panic when those arguments are not powers of two (where 0 is a power of two).
Details
Diff Detail
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
I am not confident that wherever this header is included, sys/param.h will have been included before it. Maybe you can reassure me of that.
Lately, I've found that the advice I get on header files sometimes leads me to commit things that don't compile on some architectures, because something that is included where I build isn't included for others. I don't want to repeat that mistake with this.
IMO not using sys/param.h macros would reinforce the behavior you fixed with vm_addr*() inlines, but for different case. You hand-expanded the code.
If you want, I can run make tinderbox for your patch with powerof2.
sys/vm/vm_extern.h | ||
---|---|---|
161 | There is no alignment argument for the function, it is boundary. And boundary has vm_paddr_t type, which makes it fail on most of 32bit arches. You need to use uintmax_t cast and %jx for format. BTW, it is better to use %#jx instead of manually adding 0x. |
It is almost fine except that ';' are missed at the end of panic() calls. Below is the verbatim patch that passed tinderbox:
diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h index 4e03bba66ee..9fac3403f78 100644 --- a/sys/vm/vm_extern.h +++ b/sys/vm/vm_extern.h @@ -140,6 +140,11 @@ u_int vm_wait_count(void); static inline bool vm_addr_align_ok(vm_paddr_t pa, u_long alignment) { +#ifdef INVARIANTS + if (!powerof2(alignment)) + panic("%s: alignment is not a power of 2: %#lx", + __func__, alignment); +#endif return ((pa & (alignment - 1)) == 0); } @@ -150,6 +155,11 @@ vm_addr_align_ok(vm_paddr_t pa, u_long alignment) static inline bool vm_addr_bound_ok(vm_paddr_t pa, vm_paddr_t size, vm_paddr_t boundary) { +#ifdef INVARIANTS + if (!powerof2(boundary)) + panic("%s: boundary is not a power of 2: %#jx", + __func__, (uintmax_t)boundary); +#endif return (((pa ^ (pa + size - 1)) & -boundary) == 0); }
Add semicolons.
You could argue that I should write the alignment test as
return (pa == roundup2(pa));
and the boundary test as
return (roundup2(pa, boundary) >= pa + size);
if you want the implementation to rely on sys/param.h for all its bit-trickery.
Make tinderbox completed with just these errors:
powerpc.powerpc64: make[6]: "/freebsd/dougm/base/src/stand/kboot/Makefile" line 27: Cannot open /fr
eebsd/dougm/base/src/stand/kboot/arch/powerpc/Makefile.inc
i386 LINT-NOIP:
ld: error: undefined symbol: tcp_lro_flush_all
referenced by lio_droq.c
lio_droq.o:(lio_droq_process_packets)
ld: error: undefined symbol: tcp_lro_rx
referenced by lio_core.c
lio_core.o:(lio_push_packet)
ld: error: undefined symbol: tcp_lro_init
referenced by lio_main.c
lio_main.o:(lio_attach)
ld: error: undefined symbol: tcp_lro_free
referenced by lio_main.c
lio_main.o:(lio_attach)referenced by lio_main.c
lio_main.o:(lio_destroy_nic_device)
I don't think either of these problems is associated with my changes.
I plan to either commit or discard this change within a couple of days. Please let me know how to proceed.
sys/vm/vm_extern.h | ||
---|---|---|
148 | For what it's worth, this could be written as | |
163 | For what it's worth, this could be written as return (rounddown2(pa + size - 1, boundary) <= pa); |
sys/vm/vm_extern.h | ||
---|---|---|
148 | I don't see how that makes anything clearer. On the other hand, using powerof2() provides clarity. |