mirror of
https://github.com/ceph/ceph
synced 2025-01-01 08:32:24 +00:00
Merge pull request #9524 from liewegas/wip-ctz
common: add cbits/ctz/clz bit op helpers, replace open-coded calc_bits_for helpers Reviewed-by: Samuel Just <sjust@redhat.com>
This commit is contained in:
commit
e09acd7b54
@ -16,6 +16,7 @@
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
#include "include/intarith.h"
|
||||
#include "include/encoding.h"
|
||||
|
||||
namespace ceph {
|
||||
@ -59,21 +60,12 @@ public:
|
||||
}
|
||||
|
||||
void add(int32_t v) {
|
||||
int bin = calc_bits_of(v);
|
||||
int bin = cbits(v);
|
||||
_expand_to(bin + 1);
|
||||
h[bin]++;
|
||||
_contract();
|
||||
}
|
||||
|
||||
static int calc_bits_of(int t) {
|
||||
int b = 0;
|
||||
while (t > 0) {
|
||||
t = t >> 1;
|
||||
b++;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
bool operator==(const pow2_hist_t &r) const {
|
||||
return h == r.h;
|
||||
}
|
||||
@ -89,7 +81,7 @@ public:
|
||||
int get_position_micro(int32_t v, uint64_t *lower, uint64_t *upper) {
|
||||
if (v < 0)
|
||||
return -1;
|
||||
unsigned bin = calc_bits_of(v);
|
||||
unsigned bin = cbits(v);
|
||||
uint64_t lower_sum = 0, upper_sum = 0, total = 0;
|
||||
for (unsigned i=0; i<h.size(); ++i) {
|
||||
if (i <= bin)
|
||||
|
@ -35,4 +35,57 @@
|
||||
# define SHIFT_ROUND_UP(x,y) (((x)+(1<<(y))-1) >> (y))
|
||||
#endif
|
||||
|
||||
// count trailing zeros.
|
||||
// NOTE: the builtin is nondeterministic on 0 input
|
||||
static inline unsigned ctz(unsigned v) {
|
||||
if (v == 0)
|
||||
return sizeof(v) * 8;
|
||||
return __builtin_ctz(v);
|
||||
}
|
||||
static inline unsigned ctzl(unsigned long v) {
|
||||
if (v == 0)
|
||||
return sizeof(v) * 8;
|
||||
return __builtin_ctzl(v);
|
||||
}
|
||||
static inline unsigned ctzll(unsigned long long v) {
|
||||
if (v == 0)
|
||||
return sizeof(v) * 8;
|
||||
return __builtin_ctzll(v);
|
||||
}
|
||||
|
||||
// count leading zeros
|
||||
// NOTE: the builtin is nondeterministic on 0 input
|
||||
static inline unsigned clz(unsigned v) {
|
||||
if (v == 0)
|
||||
return sizeof(v) * 8;
|
||||
return __builtin_clz(v);
|
||||
}
|
||||
static inline unsigned clzl(unsigned long v) {
|
||||
if (v == 0)
|
||||
return sizeof(v) * 8;
|
||||
return __builtin_clzl(v);
|
||||
}
|
||||
static inline unsigned clzll(unsigned long long v) {
|
||||
if (v == 0)
|
||||
return sizeof(v) * 8;
|
||||
return __builtin_clzll(v);
|
||||
}
|
||||
|
||||
// count bits (set + any 0's that follow)
|
||||
static inline unsigned cbits(unsigned v) {
|
||||
if (v == 0)
|
||||
return 0;
|
||||
return (sizeof(v) * 8) - __builtin_clz(v);
|
||||
}
|
||||
static inline unsigned cbitsl(unsigned long v) {
|
||||
if (v == 0)
|
||||
return 0;
|
||||
return (sizeof(v) * 8) - __builtin_clzl(v);
|
||||
}
|
||||
static inline unsigned cbitsll(unsigned long long v) {
|
||||
if (v == 0)
|
||||
return 0;
|
||||
return (sizeof(v) * 8) - __builtin_clzll(v);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -962,7 +962,7 @@ void PGMonitor::register_pg(OSDMap *osdmap,
|
||||
parent = pgid;
|
||||
while (1) {
|
||||
// remove most significant bit
|
||||
int msb = pool.calc_bits_of(parent.ps());
|
||||
int msb = cbits(parent.ps());
|
||||
if (!msb)
|
||||
break;
|
||||
parent.set_ps(parent.ps() & ~(1<<(msb-1)));
|
||||
|
@ -26,11 +26,7 @@ StupidAllocator::~StupidAllocator()
|
||||
unsigned StupidAllocator::_choose_bin(uint64_t orig_len)
|
||||
{
|
||||
uint64_t len = orig_len / g_conf->bdev_block_size;
|
||||
int bin = 0;
|
||||
while (len && bin + 1 < (int)free.size()) {
|
||||
len >>= 1;
|
||||
bin++;
|
||||
}
|
||||
int bin = std::min((int)cbits(len), (int)free.size() - 1);
|
||||
dout(30) << __func__ << " len " << orig_len << " -> " << bin << dendl;
|
||||
return bin;
|
||||
}
|
||||
|
@ -464,7 +464,7 @@ ostream& operator<<(ostream& out, const spg_t &pg)
|
||||
|
||||
pg_t pg_t::get_ancestor(unsigned old_pg_num) const
|
||||
{
|
||||
int old_bits = pg_pool_t::calc_bits_of(old_pg_num);
|
||||
int old_bits = cbits(old_pg_num);
|
||||
int old_mask = (1 << old_bits) - 1;
|
||||
pg_t ret = *this;
|
||||
ret.m_seed = ceph_stable_mod(m_seed, old_pg_num, old_mask);
|
||||
@ -479,7 +479,7 @@ bool pg_t::is_split(unsigned old_pg_num, unsigned new_pg_num, set<pg_t> *childre
|
||||
|
||||
bool split = false;
|
||||
if (true) {
|
||||
int old_bits = pg_pool_t::calc_bits_of(old_pg_num);
|
||||
int old_bits = cbits(old_pg_num);
|
||||
int old_mask = (1 << old_bits) - 1;
|
||||
for (int n = 1; ; n++) {
|
||||
int next_bit = (n << (old_bits-1));
|
||||
@ -498,7 +498,7 @@ bool pg_t::is_split(unsigned old_pg_num, unsigned new_pg_num, set<pg_t> *childre
|
||||
}
|
||||
if (false) {
|
||||
// brute force
|
||||
int old_bits = pg_pool_t::calc_bits_of(old_pg_num);
|
||||
int old_bits = cbits(old_pg_num);
|
||||
int old_mask = (1 << old_bits) - 1;
|
||||
for (unsigned x = old_pg_num; x < new_pg_num; ++x) {
|
||||
unsigned o = ceph_stable_mod(x, old_pg_num, old_mask);
|
||||
@ -517,7 +517,7 @@ unsigned pg_t::get_split_bits(unsigned pg_num) const {
|
||||
assert(pg_num > 1);
|
||||
|
||||
// Find unique p such that pg_num \in [2^(p-1), 2^p)
|
||||
unsigned p = pg_pool_t::calc_bits_of(pg_num);
|
||||
unsigned p = cbits(pg_num);
|
||||
assert(p); // silence coverity #751330
|
||||
|
||||
if ((m_seed % (1<<(p-1))) < (pg_num % (1<<(p-1))))
|
||||
@ -528,7 +528,7 @@ unsigned pg_t::get_split_bits(unsigned pg_num) const {
|
||||
|
||||
pg_t pg_t::get_parent() const
|
||||
{
|
||||
unsigned bits = pg_pool_t::calc_bits_of(m_seed);
|
||||
unsigned bits = cbits(m_seed);
|
||||
assert(bits);
|
||||
pg_t retval = *this;
|
||||
retval.m_seed &= ~((~0)<<(bits - 1));
|
||||
@ -1193,20 +1193,10 @@ void pg_pool_t::convert_to_pg_shards(const vector<int> &from, set<pg_shard_t>* t
|
||||
}
|
||||
}
|
||||
|
||||
int pg_pool_t::calc_bits_of(int t)
|
||||
{
|
||||
int b = 0;
|
||||
while (t > 0) {
|
||||
t = t >> 1;
|
||||
++b;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
void pg_pool_t::calc_pg_masks()
|
||||
{
|
||||
pg_num_mask = (1 << calc_bits_of(pg_num-1)) - 1;
|
||||
pgp_num_mask = (1 << calc_bits_of(pgp_num-1)) - 1;
|
||||
pg_num_mask = (1 << cbits(pg_num-1)) - 1;
|
||||
pgp_num_mask = (1 << cbits(pgp_num-1)) - 1;
|
||||
}
|
||||
|
||||
unsigned pg_pool_t::get_pg_num_divisor(pg_t pgid) const
|
||||
|
@ -1438,7 +1438,6 @@ public:
|
||||
return quota_max_objects;
|
||||
}
|
||||
|
||||
static int calc_bits_of(int t);
|
||||
void calc_pg_masks();
|
||||
|
||||
/*
|
||||
|
@ -126,6 +126,11 @@ ceph_test_rados_watch_notify_LDADD = $(LIBRADOS) libsystest.la $(PTHREAD_LIBS)
|
||||
bin_DEBUGPROGRAMS += ceph_test_rados_watch_notify
|
||||
endif # LINUX
|
||||
|
||||
unittest_intarith_SOURCES = test/test_intarith.cc
|
||||
unittest_intarith_LDADD = $(UNITTEST_LDADD)
|
||||
unittest_intarith_CXXFLAGS = $(UNITTEST_CXXFLAGS)
|
||||
check_TESTPROGRAMS += unittest_intarith
|
||||
|
||||
unittest_librados_SOURCES = test/librados/librados.cc
|
||||
unittest_librados_LDADD = $(LIBRADOS) $(CEPH_GLOBAL) $(UNITTEST_LDADD)
|
||||
unittest_librados_CXXFLAGS = $(UNITTEST_CXXFLAGS)
|
||||
|
63
src/test/test_intarith.cc
Normal file
63
src/test/test_intarith.cc
Normal file
@ -0,0 +1,63 @@
|
||||
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
|
||||
// vim: ts=8 sw=2 smarttab
|
||||
|
||||
#include <iostream>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "include/intarith.h"
|
||||
|
||||
TEST(intarith, cbits) {
|
||||
ASSERT_EQ(0u, cbits(0));
|
||||
ASSERT_EQ(1u, cbits(1));
|
||||
ASSERT_EQ(2u, cbits(2));
|
||||
ASSERT_EQ(2u, cbits(3));
|
||||
ASSERT_EQ(3u, cbits(4));
|
||||
ASSERT_EQ(0u, cbitsl(0));
|
||||
ASSERT_EQ(1u, cbitsl(1));
|
||||
ASSERT_EQ(2u, cbitsl(2));
|
||||
ASSERT_EQ(2u, cbitsl(3));
|
||||
ASSERT_EQ(3u, cbitsl(4));
|
||||
ASSERT_EQ(9u, cbits(0x100));
|
||||
ASSERT_EQ(32u, cbits(0xffffffff));
|
||||
ASSERT_EQ(32u, cbitsl(0xffffffff));
|
||||
ASSERT_EQ(32u, cbitsll(0xffffffff));
|
||||
ASSERT_EQ(64u, cbitsll(0xffffffffffffffff));
|
||||
}
|
||||
|
||||
TEST(intarith, clz) {
|
||||
ASSERT_EQ(32u, clz(0));
|
||||
ASSERT_EQ(31u, clz(1));
|
||||
ASSERT_EQ(30u, clz(2));
|
||||
ASSERT_EQ(30u, clz(3));
|
||||
ASSERT_EQ(29u, clz(4));
|
||||
ASSERT_EQ(64u, clzll(0));
|
||||
ASSERT_EQ(63u, clzll(1));
|
||||
ASSERT_EQ(62u, clzll(2));
|
||||
ASSERT_EQ(62u, clzll(3));
|
||||
ASSERT_EQ(61u, clzll(4));
|
||||
ASSERT_EQ(23u, clz(0x100));
|
||||
ASSERT_EQ(55u, clzll(0x100));
|
||||
ASSERT_EQ(0u, clz(0xffffffff));
|
||||
ASSERT_EQ(32u, clzll(0xffffffff));
|
||||
ASSERT_EQ(0u, clzll(0xffffffffffffffff));
|
||||
}
|
||||
|
||||
TEST(intarith, ctz) {
|
||||
ASSERT_EQ(32u, ctz(0));
|
||||
ASSERT_EQ(0u, ctz(1));
|
||||
ASSERT_EQ(1u, ctz(2));
|
||||
ASSERT_EQ(0u, ctz(3));
|
||||
ASSERT_EQ(2u, ctz(4));
|
||||
ASSERT_EQ(64u, ctzll(0));
|
||||
ASSERT_EQ(0u, ctzll(1));
|
||||
ASSERT_EQ(1u, ctzll(2));
|
||||
ASSERT_EQ(0u, ctzll(3));
|
||||
ASSERT_EQ(2u, ctzll(4));
|
||||
ASSERT_EQ(8u, ctz(0x100));
|
||||
ASSERT_EQ(8u, ctzll(0x100));
|
||||
ASSERT_EQ(0u, ctz(0xffffffff));
|
||||
ASSERT_EQ(0u, ctzl(0xffffffff));
|
||||
ASSERT_EQ(0u, ctzll(0xffffffff));
|
||||
ASSERT_EQ(20u, ctzll(0xffffffff00000));
|
||||
ASSERT_EQ(48u, ctzll(0xff000000000000ull));
|
||||
}
|
Loading…
Reference in New Issue
Block a user