Changeset View
Changeset View
Standalone View
Standalone View
tests/sys/sys/bitset_test.c
- This file was added.
/*- | |||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | |||||
* | |||||
* Copyright (c) 2021 The FreeBSD Foundation | |||||
* | |||||
* This software was developed by Mark Johnston under sponsorship from | |||||
* the FreeBSD Foundation. | |||||
*/ | |||||
#include <sys/types.h> | |||||
#include <sys/_bitset.h> | |||||
#include <sys/bitset.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <atf-c.h> | |||||
BITSET_DEFINE(bs256, 256); | |||||
ATF_TC_WITHOUT_HEAD(bit_foreach); | |||||
ATF_TC_BODY(bit_foreach, tc) | |||||
{ | |||||
struct bs256 bs0, bs1, bsrand; | |||||
int setc, clrc, i; | |||||
#define _BIT_FOREACH_COUNT(s, bs) do { \ | |||||
int prev = -1; \ | |||||
setc = clrc = 0; \ | |||||
BIT_FOREACH_ISSET((s), i, (bs)) { \ | |||||
ATF_REQUIRE_MSG(prev < i, "incorrect bit ordering"); \ | |||||
ATF_REQUIRE_MSG(BIT_ISSET((s), i, (bs)), \ | |||||
"bit %d is not set", i); \ | |||||
setc++; \ | |||||
prev = i; \ | |||||
} \ | |||||
prev = -1; \ | |||||
BIT_FOREACH_ISCLR((s), i, (bs)) { \ | |||||
ATF_REQUIRE_MSG(prev < i, "incorrect bit ordering"); \ | |||||
ATF_REQUIRE_MSG(!BIT_ISSET((s), i, (bs)), \ | |||||
"bit %d is set", i); \ | |||||
clrc++; \ | |||||
prev = i; \ | |||||
} \ | |||||
} while (0) | |||||
/* | |||||
* Create several bitsets, and for each one count the number | |||||
* of set and clear bits and make sure they match what we expect. | |||||
*/ | |||||
BIT_FILL(256, &bs1); | |||||
_BIT_FOREACH_COUNT(256, &bs1); | |||||
ATF_REQUIRE_MSG(setc == 256, "incorrect set count %d", setc); | |||||
ATF_REQUIRE_MSG(clrc == 0, "incorrect clear count %d", clrc); | |||||
BIT_ZERO(256, &bs0); | |||||
_BIT_FOREACH_COUNT(256, &bs0); | |||||
ATF_REQUIRE_MSG(setc == 0, "incorrect set count %d", setc); | |||||
ATF_REQUIRE_MSG(clrc == 256, "incorrect clear count %d", clrc); | |||||
BIT_ZERO(256, &bsrand); | |||||
for (i = 0; i < 256; i++) | |||||
if (random() % 2 != 0) | |||||
BIT_SET(256, i, &bsrand); | |||||
_BIT_FOREACH_COUNT(256, &bsrand); | |||||
ATF_REQUIRE_MSG(setc + clrc == 256, "incorrect counts %d, %d", | |||||
setc, clrc); | |||||
/* | |||||
* Try to verify that we can safely clear bits in the set while | |||||
* iterating. | |||||
*/ | |||||
BIT_FOREACH_ISSET(256, i, &bsrand) { | |||||
rlibby: Hmm, should we mention this in the doc? If you modify a bitset while you're iterating it, you… | |||||
Done Inline ActionsI will add a note to the manual page. I think the current behaviour is sane though. queue.h macros have some similar constraints: for example, one cannot insert an item following the current item in a TAILQ_FOREACH_SAFE traversal and expect to visit the new item during the next iteration. markj: I will add a note to the manual page. I think the current behaviour is sane though. queue.h… | |||||
ATF_REQUIRE(setc-- > 0); | |||||
BIT_CLR(256, i, &bsrand); | |||||
} | |||||
_BIT_FOREACH_COUNT(256, &bsrand); | |||||
ATF_REQUIRE_MSG(setc == 0, "incorrect set count %d", setc); | |||||
ATF_REQUIRE_MSG(clrc == 256, "incorrect clear count %d", clrc); | |||||
#undef _BIT_FOREACH_COUNT | |||||
} | |||||
ATF_TP_ADD_TCS(tp) | |||||
{ | |||||
ATF_TP_ADD_TC(tp, bit_foreach); | |||||
return (atf_no_error()); | |||||
} |
Hmm, should we mention this in the doc? If you modify a bitset while you're iterating it, you might not see that modification reflected in the iteration (if it's a later bit in the same word). I think this is acceptable but it is a potential gotcha.
Alternately, we could make it work by reloading the word and doing some shifting, but it would probably be slower for all users and most code would probably not do such a thing.