Index: UPDATING =================================================================== --- UPDATING +++ UPDATING @@ -31,6 +31,12 @@ disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20160506: + The bitstring(3) API has been updated with new functionality and + improved performance. But it is binary-incompatible with the old API. + Objects built with the new headers may not be linked against objects + built with the old headers. + 20160414: The CAM I/O scheduler has been committed to the kernel. There should be no user visible impact. This does enable NCQ Trim on ada SSDs. While the Index: share/man/man3/bitstring.3 =================================================================== --- share/man/man3/bitstring.3 +++ share/man/man3/bitstring.3 @@ -58,12 +58,13 @@ .\" @(#)bitstring.3 8.1 (Berkeley) 7/19/93 .\" $FreeBSD$ .\" -.Dd May 4, 2016 +.Dd May 6, 2016 .Dt BITSTRING 3 .Os .Sh NAME .Nm bit_alloc , .Nm bit_clear , +.Nm bit_count , .Nm bit_decl , .Nm bit_ffc , .Nm bit_ffs , @@ -84,6 +85,8 @@ .Ft void .Fn bit_clear "bitstr_t *name" "int bit" .Ft void +.Fn bit_count "bitstr_t *name" "int nbits" +.Ft void .Fn bit_ffc "bitstr_t *name" "int nbits" "int *value" .Ft void .Fn bit_ffs "bitstr_t *name" "int nbits" "int *value" @@ -225,6 +228,10 @@ .Fa value is set to \-1. .Pp +The +.Fn bit_count +function stores in the location referenced by value the number of bits set in the array of nbits bits referenced by name. +.Pp The arguments in bit string macros are evaluated only once and may safely have side effects. .Sh EXAMPLES Index: sys/kern/subr_unit.c =================================================================== --- sys/kern/subr_unit.c +++ sys/kern/subr_unit.c @@ -224,7 +224,8 @@ { struct unr *up; struct unrb *ub; - u_int x, y, z, w; + int w; + u_int y, z; y = uh->first; z = 0; @@ -237,9 +238,7 @@ up->len, NBITS, line)); z++; w = 0; - for (x = 0; x < up->len; x++) - if (bit_test(ub->map, x)) - w++; + bit_count(ub->map, up->len, &w); y += w; } else if (up->ptr != NULL) y += up->len; Index: sys/sys/bitstring.h =================================================================== --- sys/sys/bitstring.h +++ sys/sys/bitstring.h @@ -65,6 +65,7 @@ #ifdef _KERNEL #include #include +#include #endif typedef unsigned long bitstr_t; @@ -202,7 +203,7 @@ _test &= _bit_make_mask(_start, _BITSTR_BITS - 1); while (_test == 0 && _curbitstr < _stopbitstr) _test = *(++_curbitstr); - + _offset = ffsl(_test); _value = ((_curbitstr - _bitstr) * _BITSTR_BITS) + _offset - 1; if (_offset == 0 || _value >= _nbits) @@ -231,7 +232,7 @@ _test |= _bit_make_mask(0, _start - 1); while (_test == _BITSTR_MASK && _curbitstr < _stopbitstr) _test = *(++_curbitstr); - + _offset = ffsl(~_test); _value = ((_curbitstr - _bitstr) * _BITSTR_BITS) + _offset - 1; if (_offset == 0 || _value >= _nbits) @@ -256,4 +257,24 @@ bit_ffc_at(_bitstr, /*start*/0, _nbits, _result); } +/* Count the number of bits set in a bitstr of size _nbits */ +static inline void +bit_count(bitstr_t *_bitstr, int _nbits, int *_result) +{ + bitstr_t *_curbitstr; + int _value = 0; + + _curbitstr = _bitstr; + while (_nbits > 0) { + int curbitstr_len = MIN((int)_BITSTR_BITS, _nbits); + bitstr_t mask = _bit_make_mask(0, _bit_offset(curbitstr_len - 1)); + _value += __bitcountl(*_curbitstr & mask); + _curbitstr++; + _nbits -= _BITSTR_BITS; + + } + + *_result = _value; +} + #endif /* _SYS_BITSTRING_H_ */ Index: sys/sys/param.h =================================================================== --- sys/sys/param.h +++ sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1100107 /* Master, propagated to newvers */ +#define __FreeBSD_version 1100108 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, Index: tests/sys/kern/Makefile =================================================================== --- tests/sys/kern/Makefile +++ tests/sys/kern/Makefile @@ -26,8 +26,6 @@ # included in userland. But as far as subr_unit_test goes, they're effectively # static. So it's ok to disable -Wmissing-prototypes for this program. CFLAGS.subr_unit.c+= -Wno-missing-prototypes -# XXX: -Wno-sign-compare will be eliminated as part of D6004 -CFLAGS.subr_unit.c+= -Wno-sign-compare SRCS.subr_unit_test+= subr_unit.c WARNS?= 5 Index: tests/sys/sys/bitstring_test.c =================================================================== --- tests/sys/sys/bitstring_test.c +++ tests/sys/sys/bitstring_test.c @@ -342,6 +342,40 @@ } } +BITSTRING_TC_DEFINE(bit_count) +/* bitstr_t *bitstr, int nbits, const char *memloc */ +{ + int result; + + /* Empty bitstr */ + memset(bitstr, 0, bitstr_size(nbits)); + bit_count(bitstr, nbits, &result); + ATF_CHECK_MSG(0 == result, + "bit_count_%d_%s_%s: Failed with result %d", + nbits, "clear", memloc, result); + + /* Full bitstr */ + memset(bitstr, 0xFF, bitstr_size(nbits)); + bit_count(bitstr, nbits, &result); + ATF_CHECK_MSG(nbits == result, + "bit_count_%d_%s_%s: Failed with result %d", + nbits, "set", memloc, result); + + /* Alternating bitstr, starts with 0 */ + memset(bitstr, 0xAA, bitstr_size(nbits)); + bit_count(bitstr, nbits, &result); + ATF_CHECK_MSG(nbits / 2 == result, + "bit_count_%d_%s_%d_%s: Failed with result %d", + nbits, "alternating", 0, memloc, result); + + /* Alternating bitstr, starts with 1 */ + memset(bitstr, 0x55, bitstr_size(nbits)); + bit_count(bitstr, nbits, &result); + ATF_CHECK_MSG((nbits + 1) / 2 == result, + "bit_count_%d_%s_%d_%s: Failed with result %d", + nbits, "alternating", 1, memloc, result); +} + ATF_TP_ADD_TCS(tp) { @@ -354,6 +388,7 @@ BITSTRING_TC_ADD(tp, bit_ffc_at); BITSTRING_TC_ADD(tp, bit_nclear); BITSTRING_TC_ADD(tp, bit_nset); + BITSTRING_TC_ADD(tp, bit_count); return (atf_no_error()); }