2017-03-04 02:10:08 +08:00
|
|
|
#ifndef JEMALLOC_INTERNAL_BIT_UTIL_H
|
|
|
|
#define JEMALLOC_INTERNAL_BIT_UTIL_H
|
|
|
|
|
|
|
|
#include "jemalloc/internal/assert.h"
|
2012-03-07 06:57:45 +08:00
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
#define BIT_UTIL_INLINE static inline
|
2014-05-29 10:37:02 +08:00
|
|
|
|
2014-12-09 06:40:14 +08:00
|
|
|
/* Sanity check. */
|
2016-02-21 15:41:33 +08:00
|
|
|
#if !defined(JEMALLOC_INTERNAL_FFSLL) || !defined(JEMALLOC_INTERNAL_FFSL) \
|
|
|
|
|| !defined(JEMALLOC_INTERNAL_FFS)
|
|
|
|
# error JEMALLOC_INTERNAL_FFS{,L,LL} should have been defined by configure
|
2014-05-29 10:37:02 +08:00
|
|
|
#endif
|
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
|
|
|
|
BIT_UTIL_INLINE unsigned
|
2017-01-16 08:56:30 +08:00
|
|
|
ffs_llu(unsigned long long bitmap) {
|
2017-01-20 10:15:45 +08:00
|
|
|
return JEMALLOC_INTERNAL_FFSLL(bitmap);
|
2016-02-21 15:41:33 +08:00
|
|
|
}
|
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE unsigned
|
2017-01-16 08:56:30 +08:00
|
|
|
ffs_lu(unsigned long bitmap) {
|
2017-01-20 10:15:45 +08:00
|
|
|
return JEMALLOC_INTERNAL_FFSL(bitmap);
|
2014-05-29 10:37:02 +08:00
|
|
|
}
|
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE unsigned
|
2017-01-16 08:56:30 +08:00
|
|
|
ffs_u(unsigned bitmap) {
|
2017-01-20 10:15:45 +08:00
|
|
|
return JEMALLOC_INTERNAL_FFS(bitmap);
|
2014-05-29 10:37:02 +08:00
|
|
|
}
|
|
|
|
|
2018-10-30 07:01:09 +08:00
|
|
|
#ifdef JEMALLOC_INTERNAL_POPCOUNTL
|
|
|
|
BIT_UTIL_INLINE unsigned
|
|
|
|
popcount_lu(unsigned long bitmap) {
|
|
|
|
return JEMALLOC_INTERNAL_POPCOUNTL(bitmap);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clears first unset bit in bitmap, and returns
|
|
|
|
* place of bit. bitmap *must not* be 0.
|
|
|
|
*/
|
|
|
|
|
|
|
|
BIT_UTIL_INLINE size_t
|
|
|
|
cfs_lu(unsigned long* bitmap) {
|
|
|
|
size_t bit = ffs_lu(*bitmap) - 1;
|
|
|
|
*bitmap ^= ZU(1) << bit;
|
|
|
|
return bit;
|
|
|
|
}
|
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE unsigned
|
2017-01-16 08:56:30 +08:00
|
|
|
ffs_zu(size_t bitmap) {
|
2016-02-25 06:01:47 +08:00
|
|
|
#if LG_SIZEOF_PTR == LG_SIZEOF_INT
|
2017-01-20 10:15:45 +08:00
|
|
|
return ffs_u(bitmap);
|
2016-02-25 06:01:47 +08:00
|
|
|
#elif LG_SIZEOF_PTR == LG_SIZEOF_LONG
|
2017-01-20 10:15:45 +08:00
|
|
|
return ffs_lu(bitmap);
|
2016-02-25 06:01:47 +08:00
|
|
|
#elif LG_SIZEOF_PTR == LG_SIZEOF_LONG_LONG
|
2017-01-20 10:15:45 +08:00
|
|
|
return ffs_llu(bitmap);
|
2016-02-25 02:32:45 +08:00
|
|
|
#else
|
|
|
|
#error No implementation for size_t ffs()
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE unsigned
|
2017-01-16 08:56:30 +08:00
|
|
|
ffs_u64(uint64_t bitmap) {
|
2016-02-25 02:32:45 +08:00
|
|
|
#if LG_SIZEOF_LONG == 3
|
2017-01-20 10:15:45 +08:00
|
|
|
return ffs_lu(bitmap);
|
2016-02-25 02:32:45 +08:00
|
|
|
#elif LG_SIZEOF_LONG_LONG == 3
|
2017-01-20 10:15:45 +08:00
|
|
|
return ffs_llu(bitmap);
|
2016-02-25 02:32:45 +08:00
|
|
|
#else
|
|
|
|
#error No implementation for 64-bit ffs()
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE unsigned
|
2017-01-16 08:56:30 +08:00
|
|
|
ffs_u32(uint32_t bitmap) {
|
2016-02-25 02:32:45 +08:00
|
|
|
#if LG_SIZEOF_INT == 2
|
2017-01-20 10:15:45 +08:00
|
|
|
return ffs_u(bitmap);
|
2016-02-25 02:32:45 +08:00
|
|
|
#else
|
|
|
|
#error No implementation for 32-bit ffs()
|
|
|
|
#endif
|
2017-01-20 10:15:45 +08:00
|
|
|
return ffs_u(bitmap);
|
2016-02-25 02:32:45 +08:00
|
|
|
}
|
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE uint64_t
|
2017-01-16 08:56:30 +08:00
|
|
|
pow2_ceil_u64(uint64_t x) {
|
2018-08-11 11:27:35 +08:00
|
|
|
#if (defined(__amd64__) || defined(__x86_64__) || defined(JEMALLOC_HAVE_BUILTIN_CLZ))
|
|
|
|
if(unlikely(x <= 1)) {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
size_t msb_on_index;
|
|
|
|
#if (defined(__amd64__) || defined(__x86_64__))
|
|
|
|
asm ("bsrq %1, %0"
|
|
|
|
: "=r"(msb_on_index) // Outputs.
|
|
|
|
: "r"(x-1) // Inputs.
|
|
|
|
);
|
|
|
|
#elif (defined(JEMALLOC_HAVE_BUILTIN_CLZ))
|
|
|
|
msb_on_index = (63 ^ __builtin_clzll(x - 1));
|
|
|
|
#endif
|
|
|
|
assert(msb_on_index < 63);
|
|
|
|
return 1ULL << (msb_on_index + 1);
|
|
|
|
#else
|
2012-03-07 06:57:45 +08:00
|
|
|
x--;
|
|
|
|
x |= x >> 1;
|
|
|
|
x |= x >> 2;
|
|
|
|
x |= x >> 4;
|
|
|
|
x |= x >> 8;
|
|
|
|
x |= x >> 16;
|
|
|
|
x |= x >> 32;
|
|
|
|
x++;
|
2017-01-20 10:15:45 +08:00
|
|
|
return x;
|
2018-08-11 11:27:35 +08:00
|
|
|
#endif
|
2012-03-07 06:57:45 +08:00
|
|
|
}
|
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE uint32_t
|
2017-01-16 08:56:30 +08:00
|
|
|
pow2_ceil_u32(uint32_t x) {
|
2018-08-24 11:58:48 +08:00
|
|
|
#if ((defined(__i386__) || defined(JEMALLOC_HAVE_BUILTIN_CLZ)) && (!defined(__s390__)))
|
2018-08-11 11:27:35 +08:00
|
|
|
if(unlikely(x <= 1)) {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
size_t msb_on_index;
|
|
|
|
#if (defined(__i386__))
|
|
|
|
asm ("bsr %1, %0"
|
|
|
|
: "=r"(msb_on_index) // Outputs.
|
|
|
|
: "r"(x-1) // Inputs.
|
|
|
|
);
|
|
|
|
#elif (defined(JEMALLOC_HAVE_BUILTIN_CLZ))
|
|
|
|
msb_on_index = (31 ^ __builtin_clz(x - 1));
|
|
|
|
#endif
|
|
|
|
assert(msb_on_index < 31);
|
|
|
|
return 1U << (msb_on_index + 1);
|
|
|
|
#else
|
2016-02-10 08:28:40 +08:00
|
|
|
x--;
|
|
|
|
x |= x >> 1;
|
|
|
|
x |= x >> 2;
|
|
|
|
x |= x >> 4;
|
|
|
|
x |= x >> 8;
|
|
|
|
x |= x >> 16;
|
|
|
|
x++;
|
2017-01-20 10:15:45 +08:00
|
|
|
return x;
|
2018-08-11 11:27:35 +08:00
|
|
|
#endif
|
2016-02-10 08:28:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compute the smallest power of 2 that is >= x. */
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE size_t
|
2017-01-16 08:56:30 +08:00
|
|
|
pow2_ceil_zu(size_t x) {
|
2016-02-10 08:28:40 +08:00
|
|
|
#if (LG_SIZEOF_PTR == 3)
|
2017-01-20 10:15:45 +08:00
|
|
|
return pow2_ceil_u64(x);
|
2016-02-10 08:28:40 +08:00
|
|
|
#else
|
2017-01-20 10:15:45 +08:00
|
|
|
return pow2_ceil_u32(x);
|
2016-02-10 08:28:40 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-05-29 07:11:55 +08:00
|
|
|
#if (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE unsigned
|
2017-01-16 08:56:30 +08:00
|
|
|
lg_floor(size_t x) {
|
2014-05-29 07:11:55 +08:00
|
|
|
size_t ret;
|
2015-02-05 08:41:55 +08:00
|
|
|
assert(x != 0);
|
|
|
|
|
2014-05-29 07:11:55 +08:00
|
|
|
asm ("bsr %1, %0"
|
|
|
|
: "=r"(ret) // Outputs.
|
|
|
|
: "r"(x) // Inputs.
|
|
|
|
);
|
2016-02-25 03:04:51 +08:00
|
|
|
assert(ret < UINT_MAX);
|
2017-01-20 10:15:45 +08:00
|
|
|
return (unsigned)ret;
|
2014-05-29 07:11:55 +08:00
|
|
|
}
|
2014-09-22 22:54:33 +08:00
|
|
|
#elif (defined(_MSC_VER))
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE unsigned
|
2017-01-16 08:56:30 +08:00
|
|
|
lg_floor(size_t x) {
|
2015-02-05 08:41:55 +08:00
|
|
|
unsigned long ret;
|
|
|
|
|
|
|
|
assert(x != 0);
|
2014-09-22 22:54:33 +08:00
|
|
|
|
|
|
|
#if (LG_SIZEOF_PTR == 3)
|
2015-02-05 08:41:55 +08:00
|
|
|
_BitScanReverse64(&ret, x);
|
2014-09-22 22:54:33 +08:00
|
|
|
#elif (LG_SIZEOF_PTR == 2)
|
2015-02-05 08:41:55 +08:00
|
|
|
_BitScanReverse(&ret, x);
|
2014-09-22 22:54:33 +08:00
|
|
|
#else
|
2016-02-25 02:32:45 +08:00
|
|
|
# error "Unsupported type size for lg_floor()"
|
2014-09-22 22:54:33 +08:00
|
|
|
#endif
|
2016-02-25 03:04:51 +08:00
|
|
|
assert(ret < UINT_MAX);
|
2017-01-20 10:15:45 +08:00
|
|
|
return (unsigned)ret;
|
2014-09-22 22:54:33 +08:00
|
|
|
}
|
2014-05-29 07:11:55 +08:00
|
|
|
#elif (defined(JEMALLOC_HAVE_BUILTIN_CLZ))
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE unsigned
|
2017-01-16 08:56:30 +08:00
|
|
|
lg_floor(size_t x) {
|
2015-02-05 08:41:55 +08:00
|
|
|
assert(x != 0);
|
|
|
|
|
2014-05-29 07:11:55 +08:00
|
|
|
#if (LG_SIZEOF_PTR == LG_SIZEOF_INT)
|
2017-01-20 10:15:45 +08:00
|
|
|
return ((8 << LG_SIZEOF_PTR) - 1) - __builtin_clz(x);
|
2014-05-29 07:11:55 +08:00
|
|
|
#elif (LG_SIZEOF_PTR == LG_SIZEOF_LONG)
|
2017-01-20 10:15:45 +08:00
|
|
|
return ((8 << LG_SIZEOF_PTR) - 1) - __builtin_clzl(x);
|
2014-05-29 07:11:55 +08:00
|
|
|
#else
|
2016-02-25 02:32:45 +08:00
|
|
|
# error "Unsupported type size for lg_floor()"
|
2014-05-29 07:11:55 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#else
|
2017-03-04 02:10:08 +08:00
|
|
|
BIT_UTIL_INLINE unsigned
|
2017-01-16 08:56:30 +08:00
|
|
|
lg_floor(size_t x) {
|
2015-02-05 08:41:55 +08:00
|
|
|
assert(x != 0);
|
|
|
|
|
2014-06-02 13:05:08 +08:00
|
|
|
x |= (x >> 1);
|
|
|
|
x |= (x >> 2);
|
|
|
|
x |= (x >> 4);
|
|
|
|
x |= (x >> 8);
|
|
|
|
x |= (x >> 16);
|
2016-02-25 02:32:45 +08:00
|
|
|
#if (LG_SIZEOF_PTR == 3)
|
2014-06-02 13:05:08 +08:00
|
|
|
x |= (x >> 32);
|
2014-05-29 07:11:55 +08:00
|
|
|
#endif
|
2017-01-16 08:56:30 +08:00
|
|
|
if (x == SIZE_T_MAX) {
|
2017-01-20 10:15:45 +08:00
|
|
|
return (8 << LG_SIZEOF_PTR) - 1;
|
2017-01-16 08:56:30 +08:00
|
|
|
}
|
2016-02-25 02:32:45 +08:00
|
|
|
x++;
|
2017-01-20 10:15:45 +08:00
|
|
|
return ffs_zu(x) - 2;
|
2014-05-29 07:11:55 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-12-23 07:14:44 +08:00
|
|
|
BIT_UTIL_INLINE unsigned
|
|
|
|
lg_ceil(size_t x) {
|
|
|
|
return lg_floor(x) + ((x & (x - 1)) == 0 ? 0 : 1);
|
|
|
|
}
|
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
#undef BIT_UTIL_INLINE
|
2012-03-07 06:57:45 +08:00
|
|
|
|
2017-12-23 07:14:44 +08:00
|
|
|
/* A compile-time version of lg_floor and lg_ceil. */
|
|
|
|
#define LG_FLOOR_1(x) 0
|
|
|
|
#define LG_FLOOR_2(x) (x < (1ULL << 1) ? LG_FLOOR_1(x) : 1 + LG_FLOOR_1(x >> 1))
|
|
|
|
#define LG_FLOOR_4(x) (x < (1ULL << 2) ? LG_FLOOR_2(x) : 2 + LG_FLOOR_2(x >> 2))
|
|
|
|
#define LG_FLOOR_8(x) (x < (1ULL << 4) ? LG_FLOOR_4(x) : 4 + LG_FLOOR_4(x >> 4))
|
|
|
|
#define LG_FLOOR_16(x) (x < (1ULL << 8) ? LG_FLOOR_8(x) : 8 + LG_FLOOR_8(x >> 8))
|
|
|
|
#define LG_FLOOR_32(x) (x < (1ULL << 16) ? LG_FLOOR_16(x) : 16 + LG_FLOOR_16(x >> 16))
|
|
|
|
#define LG_FLOOR_64(x) (x < (1ULL << 32) ? LG_FLOOR_32(x) : 32 + LG_FLOOR_32(x >> 32))
|
|
|
|
#if LG_SIZEOF_PTR == 2
|
|
|
|
# define LG_FLOOR(x) LG_FLOOR_32((x))
|
|
|
|
#else
|
|
|
|
# define LG_FLOOR(x) LG_FLOOR_64((x))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define LG_CEIL(x) (LG_FLOOR(x) + (((x) & ((x) - 1)) == 0 ? 0 : 1))
|
2017-12-15 04:46:39 +08:00
|
|
|
|
2017-03-04 02:10:08 +08:00
|
|
|
#endif /* JEMALLOC_INTERNAL_BIT_UTIL_H */
|