mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-01-14 16:47:59 +08:00
review bitmap.c
This commit is contained in:
parent
91cd6e2560
commit
10a6b303be
89
src/bitmap.c
89
src/bitmap.c
@ -11,7 +11,6 @@ represeted as an array of fields where each field is a machine word (`size_t`)
|
|||||||
|
|
||||||
There are two api's; the standard one cannot have sequences that cross
|
There are two api's; the standard one cannot have sequences that cross
|
||||||
between the bitmap fields (and a sequence must be <= MI_BITMAP_FIELD_BITS).
|
between the bitmap fields (and a sequence must be <= MI_BITMAP_FIELD_BITS).
|
||||||
(this is used in region allocation)
|
|
||||||
|
|
||||||
The `_across` postfixed functions do allow sequences that can cross over
|
The `_across` postfixed functions do allow sequences that can cross over
|
||||||
between the fields. (This is used in arena allocation)
|
between the fields. (This is used in arena allocation)
|
||||||
@ -63,12 +62,12 @@ bool _mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_
|
|||||||
|
|
||||||
// scan linearly for a free range of zero bits
|
// scan linearly for a free range of zero bits
|
||||||
while (bitidx <= bitidx_max) {
|
while (bitidx <= bitidx_max) {
|
||||||
const size_t mapm = map & m;
|
const size_t mapm = (map & m);
|
||||||
if (mapm == 0) { // are the mask bits free at bitidx?
|
if (mapm == 0) { // are the mask bits free at bitidx?
|
||||||
mi_assert_internal((m >> bitidx) == mask); // no overflow?
|
mi_assert_internal((m >> bitidx) == mask); // no overflow?
|
||||||
const size_t newmap = map | m;
|
const size_t newmap = (map | m);
|
||||||
mi_assert_internal((newmap^map) >> bitidx == mask);
|
mi_assert_internal((newmap^map) >> bitidx == mask);
|
||||||
if (!mi_atomic_cas_weak_acq_rel(field, &map, newmap)) { // TODO: use strong cas here?
|
if (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)) { // TODO: use weak cas here?
|
||||||
// no success, another thread claimed concurrently.. keep going (with updated `map`)
|
// no success, another thread claimed concurrently.. keep going (with updated `map`)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -81,7 +80,8 @@ bool _mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_
|
|||||||
else {
|
else {
|
||||||
// on to the next bit range
|
// on to the next bit range
|
||||||
#ifdef MI_HAVE_FAST_BITSCAN
|
#ifdef MI_HAVE_FAST_BITSCAN
|
||||||
const size_t shift = (count == 1 ? 1 : mi_bsr(mapm) - bitidx + 1);
|
mi_assert_internal(mapm != 0);
|
||||||
|
const size_t shift = (count == 1 ? 1 : (MI_INTPTR_BITS - mi_clz(mapm) - bitidx));
|
||||||
mi_assert_internal(shift > 0 && shift <= count);
|
mi_assert_internal(shift > 0 && shift <= count);
|
||||||
#else
|
#else
|
||||||
const size_t shift = 1;
|
const size_t shift = 1;
|
||||||
@ -100,7 +100,7 @@ bool _mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_
|
|||||||
bool _mi_bitmap_try_find_from_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) {
|
bool _mi_bitmap_try_find_from_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) {
|
||||||
size_t idx = start_field_idx;
|
size_t idx = start_field_idx;
|
||||||
for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) {
|
for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) {
|
||||||
if (idx >= bitmap_fields) idx = 0; // wrap
|
if (idx >= bitmap_fields) { idx = 0; } // wrap
|
||||||
if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) {
|
if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -108,13 +108,6 @@ bool _mi_bitmap_try_find_from_claim(mi_bitmap_t bitmap, const size_t bitmap_fiel
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Find `count` bits of 0 and set them to 1 atomically; returns `true` on success.
|
|
||||||
// For now, `count` can be at most MI_BITMAP_FIELD_BITS and will never span fields.
|
|
||||||
bool _mi_bitmap_try_find_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t count, mi_bitmap_index_t* bitmap_idx) {
|
|
||||||
return _mi_bitmap_try_find_from_claim(bitmap, bitmap_fields, 0, count, bitmap_idx);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Set `count` bits at `bitmap_idx` to 0 atomically
|
// Set `count` bits at `bitmap_idx` to 0 atomically
|
||||||
// Returns `true` if all `count` bits were 1 previously.
|
// Returns `true` if all `count` bits were 1 previously.
|
||||||
@ -124,7 +117,7 @@ bool _mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count,
|
|||||||
const size_t mask = mi_bitmap_mask_(count, bitidx);
|
const size_t mask = mi_bitmap_mask_(count, bitidx);
|
||||||
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
||||||
// mi_assert_internal((bitmap[idx] & mask) == mask);
|
// mi_assert_internal((bitmap[idx] & mask) == mask);
|
||||||
size_t prev = mi_atomic_and_acq_rel(&bitmap[idx], ~mask);
|
const size_t prev = mi_atomic_and_acq_rel(&bitmap[idx], ~mask);
|
||||||
return ((prev & mask) == mask);
|
return ((prev & mask) == mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +131,7 @@ bool _mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi
|
|||||||
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
||||||
//mi_assert_internal(any_zero != NULL || (bitmap[idx] & mask) == 0);
|
//mi_assert_internal(any_zero != NULL || (bitmap[idx] & mask) == 0);
|
||||||
size_t prev = mi_atomic_or_acq_rel(&bitmap[idx], mask);
|
size_t prev = mi_atomic_or_acq_rel(&bitmap[idx], mask);
|
||||||
if (any_zero != NULL) *any_zero = ((prev & mask) != mask);
|
if (any_zero != NULL) { *any_zero = ((prev & mask) != mask); }
|
||||||
return ((prev & mask) == 0);
|
return ((prev & mask) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,8 +141,8 @@ static bool mi_bitmap_is_claimedx(mi_bitmap_t bitmap, size_t bitmap_fields, size
|
|||||||
const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
|
const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
|
||||||
const size_t mask = mi_bitmap_mask_(count, bitidx);
|
const size_t mask = mi_bitmap_mask_(count, bitidx);
|
||||||
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
||||||
size_t field = mi_atomic_load_relaxed(&bitmap[idx]);
|
const size_t field = mi_atomic_load_relaxed(&bitmap[idx]);
|
||||||
if (any_ones != NULL) *any_ones = ((field & mask) != 0);
|
if (any_ones != NULL) { *any_ones = ((field & mask) != 0); }
|
||||||
return ((field & mask) == mask);
|
return ((field & mask) == mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,10 +153,13 @@ bool _mi_bitmap_try_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count
|
|||||||
const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
|
const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
|
||||||
const size_t mask = mi_bitmap_mask_(count, bitidx);
|
const size_t mask = mi_bitmap_mask_(count, bitidx);
|
||||||
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
|
||||||
size_t expected = 0;
|
size_t expected = mi_atomic_load_relaxed(&bitmap[idx]);
|
||||||
if (mi_atomic_cas_strong_acq_rel(&bitmap[idx], &expected, mask)) return true;
|
do {
|
||||||
if ((expected & mask) != 0) return false;
|
if ((expected & mask) != 0) return false;
|
||||||
return mi_atomic_cas_strong_acq_rel(&bitmap[idx], &expected, expected | mask);
|
}
|
||||||
|
while (!mi_atomic_cas_strong_acq_rel(&bitmap[idx], &expected, expected | mask));
|
||||||
|
mi_assert_internal((expected & mask) == 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -185,6 +181,7 @@ bool _mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t
|
|||||||
|
|
||||||
// Try to atomically claim a sequence of `count` bits starting from the field
|
// Try to atomically claim a sequence of `count` bits starting from the field
|
||||||
// at `idx` in `bitmap` and crossing into subsequent fields. Returns `true` on success.
|
// at `idx` in `bitmap` and crossing into subsequent fields. Returns `true` on success.
|
||||||
|
// Only needs to consider crossing into the next fields (see `mi_bitmap_try_find_from_claim_across`)
|
||||||
static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t idx, const size_t count, const size_t retries, mi_bitmap_index_t* bitmap_idx)
|
static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t idx, const size_t count, const size_t retries, mi_bitmap_index_t* bitmap_idx)
|
||||||
{
|
{
|
||||||
mi_assert_internal(bitmap_idx != NULL);
|
mi_assert_internal(bitmap_idx != NULL);
|
||||||
@ -195,9 +192,9 @@ static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bit
|
|||||||
const size_t initial = mi_clz(map); // count of initial zeros starting at idx
|
const size_t initial = mi_clz(map); // count of initial zeros starting at idx
|
||||||
mi_assert_internal(initial <= MI_BITMAP_FIELD_BITS);
|
mi_assert_internal(initial <= MI_BITMAP_FIELD_BITS);
|
||||||
if (initial == 0) return false;
|
if (initial == 0) return false;
|
||||||
if (initial >= count) return _mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx); // no need to cross fields
|
if (initial >= count) return _mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx); // no need to cross fields (this case won't happen for us)
|
||||||
if (_mi_divide_up(count - initial, MI_BITMAP_FIELD_BITS) >= (bitmap_fields - idx)) return false; // not enough entries
|
if (_mi_divide_up(count - initial, MI_BITMAP_FIELD_BITS) >= (bitmap_fields - idx)) return false; // not enough entries
|
||||||
|
|
||||||
// scan ahead
|
// scan ahead
|
||||||
size_t found = initial;
|
size_t found = initial;
|
||||||
size_t mask = 0; // mask bits for the final field
|
size_t mask = 0; // mask bits for the final field
|
||||||
@ -205,25 +202,27 @@ static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bit
|
|||||||
field++;
|
field++;
|
||||||
map = mi_atomic_load_relaxed(field);
|
map = mi_atomic_load_relaxed(field);
|
||||||
const size_t mask_bits = (found + MI_BITMAP_FIELD_BITS <= count ? MI_BITMAP_FIELD_BITS : (count - found));
|
const size_t mask_bits = (found + MI_BITMAP_FIELD_BITS <= count ? MI_BITMAP_FIELD_BITS : (count - found));
|
||||||
|
mi_assert_internal(mask_bits > 0 && mask_bits <= MI_BITMAP_FIELD_BITS);
|
||||||
mask = mi_bitmap_mask_(mask_bits, 0);
|
mask = mi_bitmap_mask_(mask_bits, 0);
|
||||||
if ((map & mask) != 0) return false;
|
if ((map & mask) != 0) return false; // some part is already claimed
|
||||||
found += mask_bits;
|
found += mask_bits;
|
||||||
}
|
}
|
||||||
mi_assert_internal(field < &bitmap[bitmap_fields]);
|
mi_assert_internal(field < &bitmap[bitmap_fields]);
|
||||||
|
|
||||||
// found range of zeros up to the final field; mask contains mask in the final field
|
// we found a range of contiguous zeros up to the final field; mask contains mask in the final field
|
||||||
// now claim it atomically
|
// now try to claim the range atomically
|
||||||
mi_bitmap_field_t* const final_field = field;
|
mi_bitmap_field_t* const final_field = field;
|
||||||
const size_t final_mask = mask;
|
const size_t final_mask = mask;
|
||||||
mi_bitmap_field_t* const initial_field = &bitmap[idx];
|
mi_bitmap_field_t* const initial_field = &bitmap[idx];
|
||||||
const size_t initial_mask = mi_bitmap_mask_(initial, MI_BITMAP_FIELD_BITS - initial);
|
const size_t initial_idx = MI_BITMAP_FIELD_BITS - initial;
|
||||||
|
const size_t initial_mask = mi_bitmap_mask_(initial, initial_idx);
|
||||||
|
|
||||||
// initial field
|
// initial field
|
||||||
size_t newmap;
|
size_t newmap;
|
||||||
field = initial_field;
|
field = initial_field;
|
||||||
map = mi_atomic_load_relaxed(field);
|
map = mi_atomic_load_relaxed(field);
|
||||||
do {
|
do {
|
||||||
newmap = map | initial_mask;
|
newmap = (map | initial_mask);
|
||||||
if ((map & initial_mask) != 0) { goto rollback; };
|
if ((map & initial_mask) != 0) { goto rollback; };
|
||||||
} while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
|
} while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
|
||||||
|
|
||||||
@ -238,31 +237,32 @@ static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bit
|
|||||||
mi_assert_internal(field == final_field);
|
mi_assert_internal(field == final_field);
|
||||||
map = mi_atomic_load_relaxed(field);
|
map = mi_atomic_load_relaxed(field);
|
||||||
do {
|
do {
|
||||||
newmap = map | final_mask;
|
newmap = (map | final_mask);
|
||||||
if ((map & final_mask) != 0) { goto rollback; }
|
if ((map & final_mask) != 0) { goto rollback; }
|
||||||
} while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
|
} while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
|
||||||
|
|
||||||
// claimed!
|
// claimed!
|
||||||
*bitmap_idx = mi_bitmap_index_create(idx, MI_BITMAP_FIELD_BITS - initial);
|
*bitmap_idx = mi_bitmap_index_create(idx, initial_idx);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
rollback:
|
rollback:
|
||||||
// roll back intermediate fields
|
// roll back intermediate fields
|
||||||
|
// (we just failed to claim `field` so decrement first)
|
||||||
while (--field > initial_field) {
|
while (--field > initial_field) {
|
||||||
newmap = 0;
|
newmap = 0;
|
||||||
map = mi_bitmap_mask_(MI_BITMAP_FIELD_BITS, 0);
|
map = mi_bitmap_mask_(MI_BITMAP_FIELD_BITS, 0);
|
||||||
mi_assert_internal(mi_atomic_load_relaxed(field) == map);
|
mi_assert_internal(mi_atomic_load_relaxed(field) == map);
|
||||||
mi_atomic_store_release(field, newmap);
|
mi_atomic_store_release(field, newmap);
|
||||||
}
|
}
|
||||||
if (field == initial_field) {
|
if (field == initial_field) { // (if we failed on the initial field, `field + 1 == initial_field`)
|
||||||
map = mi_atomic_load_relaxed(field);
|
map = mi_atomic_load_relaxed(field);
|
||||||
do {
|
do {
|
||||||
mi_assert_internal((map & initial_mask) == initial_mask);
|
mi_assert_internal((map & initial_mask) == initial_mask);
|
||||||
newmap = map & ~initial_mask;
|
newmap = (map & ~initial_mask);
|
||||||
} while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
|
} while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
|
||||||
}
|
}
|
||||||
// retry? (we make a recursive call instead of goto to be able to use const declarations)
|
// retry? (we make a recursive call instead of goto to be able to use const declarations)
|
||||||
if (retries < 4) {
|
if (retries <= 2) {
|
||||||
return mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, retries+1, bitmap_idx);
|
return mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, retries+1, bitmap_idx);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -275,17 +275,22 @@ rollback:
|
|||||||
// Starts at idx, and wraps around to search in all `bitmap_fields` fields.
|
// Starts at idx, and wraps around to search in all `bitmap_fields` fields.
|
||||||
bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) {
|
bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) {
|
||||||
mi_assert_internal(count > 0);
|
mi_assert_internal(count > 0);
|
||||||
if (count==1) return _mi_bitmap_try_find_from_claim(bitmap, bitmap_fields, start_field_idx, count, bitmap_idx);
|
if (count <= 2) {
|
||||||
|
// we don't bother with crossover fields for small counts
|
||||||
|
return _mi_bitmap_try_find_from_claim(bitmap, bitmap_fields, start_field_idx, count, bitmap_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// visit the fields
|
||||||
size_t idx = start_field_idx;
|
size_t idx = start_field_idx;
|
||||||
for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) {
|
for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) {
|
||||||
if (idx >= bitmap_fields) idx = 0; // wrap
|
if (idx >= bitmap_fields) { idx = 0; } // wrap
|
||||||
// try to claim inside the field
|
// first try to claim inside a field
|
||||||
if (count <= MI_BITMAP_FIELD_BITS) {
|
if (count <= MI_BITMAP_FIELD_BITS) {
|
||||||
if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) {
|
if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// try to claim across fields
|
// if that fails, then try to claim across fields
|
||||||
if (mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, 0, bitmap_idx)) {
|
if (mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, 0, bitmap_idx)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -328,14 +333,14 @@ bool _mi_bitmap_unclaim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t
|
|||||||
size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);
|
size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);
|
||||||
bool all_one = true;
|
bool all_one = true;
|
||||||
mi_bitmap_field_t* field = &bitmap[idx];
|
mi_bitmap_field_t* field = &bitmap[idx];
|
||||||
size_t prev = mi_atomic_and_acq_rel(field++, ~pre_mask);
|
size_t prev = mi_atomic_and_acq_rel(field++, ~pre_mask); // clear first part
|
||||||
if ((prev & pre_mask) != pre_mask) all_one = false;
|
if ((prev & pre_mask) != pre_mask) all_one = false;
|
||||||
while(mid_count-- > 0) {
|
while(mid_count-- > 0) {
|
||||||
prev = mi_atomic_and_acq_rel(field++, ~mid_mask);
|
prev = mi_atomic_and_acq_rel(field++, ~mid_mask); // clear mid part
|
||||||
if ((prev & mid_mask) != mid_mask) all_one = false;
|
if ((prev & mid_mask) != mid_mask) all_one = false;
|
||||||
}
|
}
|
||||||
if (post_mask!=0) {
|
if (post_mask!=0) {
|
||||||
prev = mi_atomic_and_acq_rel(field, ~post_mask);
|
prev = mi_atomic_and_acq_rel(field, ~post_mask); // clear end part
|
||||||
if ((prev & post_mask) != post_mask) all_one = false;
|
if ((prev & post_mask) != post_mask) all_one = false;
|
||||||
}
|
}
|
||||||
return all_one;
|
return all_one;
|
||||||
@ -365,7 +370,7 @@ bool _mi_bitmap_claim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t co
|
|||||||
if ((prev & post_mask) != 0) all_zero = false;
|
if ((prev & post_mask) != 0) all_zero = false;
|
||||||
if ((prev & post_mask) != post_mask) any_zero = true;
|
if ((prev & post_mask) != post_mask) any_zero = true;
|
||||||
}
|
}
|
||||||
if (pany_zero != NULL) *pany_zero = any_zero;
|
if (pany_zero != NULL) { *pany_zero = any_zero; }
|
||||||
return all_zero;
|
return all_zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +399,7 @@ static bool mi_bitmap_is_claimedx_across(mi_bitmap_t bitmap, size_t bitmap_field
|
|||||||
if ((prev & post_mask) != post_mask) all_ones = false;
|
if ((prev & post_mask) != post_mask) all_ones = false;
|
||||||
if ((prev & post_mask) != 0) any_ones = true;
|
if ((prev & post_mask) != 0) any_ones = true;
|
||||||
}
|
}
|
||||||
if (pany_ones != NULL) *pany_ones = any_ones;
|
if (pany_ones != NULL) { *pany_ones = any_ones; }
|
||||||
return all_ones;
|
return all_ones;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user