Commit f2d282e1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'bitmap-for-6.17' of https://github.com/norov/linux

Pull bitmap updates from Yury Norov:

 - find_random_bit() series (Yury)

 - GENMASK() consolidation (Vincent)

 - random cleanups (Shaopeng, Ben, Yury)

* tag 'bitmap-for-6.17' of https://github.com/norov/linux:
  bitfield: Ensure the return values of helper functions are checked
  test_bits: add tests for __GENMASK() and __GENMASK_ULL()
  bits: unify the non-asm GENMASK*()
  bits: split the definition of the asm and non-asm GENMASK*()
  cpumask: Remove unnecessary cpumask_nth_andnot()
  watchdog: fix opencoded cpumask_next_wrap() in watchdog_next_cpu()
  clocksource: Improve randomness in clocksource_verify_choose_cpus()
  cpumask: introduce cpumask_random()
  bitmap: generalize node_random()
parents 6a68cec1 e2b02d38
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -189,13 +189,13 @@ static __always_inline u64 field_mask(u64 field)
}
#define field_max(field)	((typeof(field))field_mask(field))
#define ____MAKE_OP(type,base,to,from)					\
static __always_inline __##type type##_encode_bits(base v, base field)	\
static __always_inline __##type __must_check type##_encode_bits(base v, base field)	\
{									\
	if (__builtin_constant_p(v) && (v & ~field_mask(field)))	\
		__field_overflow();					\
	return to((v & field_mask(field)) * field_multiplier(field));	\
}									\
static __always_inline __##type type##_replace_bits(__##type old,	\
static __always_inline __##type __must_check type##_replace_bits(__##type old,	\
							base val, base field)	\
{									\
	return (old & ~to(field)) | type##_encode_bits(val, field);	\
@@ -205,7 +205,7 @@ static __always_inline void type##p_replace_bits(__##type *p, \
{									\
	*p = (*p & ~to(field)) | type##_encode_bits(val, field);	\
}									\
static __always_inline base type##_get_bits(__##type v, base field)	\
static __always_inline base __must_check type##_get_bits(__##type v, base field)	\
{									\
	return (from(v) & field)/field_multiplier(field);		\
}
+6 −23
Original line number Diff line number Diff line
@@ -2,10 +2,8 @@
#ifndef __LINUX_BITS_H
#define __LINUX_BITS_H

#include <linux/const.h>
#include <vdso/bits.h>
#include <uapi/linux/bits.h>
#include <asm/bitsperlong.h>

#define BIT_MASK(nr)		(UL(1) << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr)		((nr) / BITS_PER_LONG)
@@ -50,10 +48,14 @@
	     (type_max(t) << (l) &				\
	      type_max(t) >> (BITS_PER_TYPE(t) - 1 - (h)))))

#define GENMASK(h, l)		GENMASK_TYPE(unsigned long, h, l)
#define GENMASK_ULL(h, l)	GENMASK_TYPE(unsigned long long, h, l)

#define GENMASK_U8(h, l)	GENMASK_TYPE(u8, h, l)
#define GENMASK_U16(h, l)	GENMASK_TYPE(u16, h, l)
#define GENMASK_U32(h, l)	GENMASK_TYPE(u32, h, l)
#define GENMASK_U64(h, l)	GENMASK_TYPE(u64, h, l)
#define GENMASK_U128(h, l)	GENMASK_TYPE(u128, h, l)

/*
 * Fixed-type variants of BIT(), with additional checks like GENMASK_TYPE(). The
@@ -79,28 +81,9 @@
 * BUILD_BUG_ON_ZERO is not available in h files included from asm files,
 * disable the input check if that is the case.
 */
#define GENMASK_INPUT_CHECK(h, l) 0
#define GENMASK(h, l)		__GENMASK(h, l)
#define GENMASK_ULL(h, l)	__GENMASK_ULL(h, l)

#endif /* !defined(__ASSEMBLY__) */

#define GENMASK(h, l) \
	(GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
#define GENMASK_ULL(h, l) \
	(GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))

#if !defined(__ASSEMBLY__)
/*
 * Missing asm support
 *
 * __GENMASK_U128() depends on _BIT128() which would not work
 * in the asm code, as it shifts an 'unsigned __int128' data
 * type instead of direct representation of 128 bit constants
 * such as long and unsigned long. The fundamental problem is
 * that a 128 bit constant will get silently truncated by the
 * gcc compiler.
 */
#define GENMASK_U128(h, l) \
	(GENMASK_INPUT_CHECK(h, l) + __GENMASK_U128(h, l))
#endif

#endif	/* __LINUX_BITS_H */
+12 −16
Original line number Diff line number Diff line
@@ -354,6 +354,18 @@ unsigned int cpumask_next_wrap(int n, const struct cpumask *src)
	return find_next_bit_wrap(cpumask_bits(src), small_cpumask_bits, n + 1);
}

/**
 * cpumask_random - get random cpu in *src.
 * @src: cpumask pointer
 *
 * Return: random set bit, or >= nr_cpu_ids if @src is empty.
 */
static __always_inline
unsigned int cpumask_random(const struct cpumask *src)
{
	return find_random_bit(cpumask_bits(src), nr_cpu_ids);
}

/**
 * for_each_cpu - iterate over every cpu in a mask
 * @cpu: the (optionally unsigned) integer iterator
@@ -546,22 +558,6 @@ unsigned int cpumask_nth_and(unsigned int cpu, const struct cpumask *srcp1,
				small_cpumask_bits, cpumask_check(cpu));
}

/**
 * cpumask_nth_andnot - get the Nth cpu set in 1st cpumask, and clear in 2nd.
 * @srcp1: the cpumask pointer
 * @srcp2: the cpumask pointer
 * @cpu: the Nth cpu to find, starting from 0
 *
 * Return: >= nr_cpu_ids if such cpu doesn't exist.
 */
static __always_inline
unsigned int cpumask_nth_andnot(unsigned int cpu, const struct cpumask *srcp1,
							const struct cpumask *srcp2)
{
	return find_nth_andnot_bit(cpumask_bits(srcp1), cpumask_bits(srcp2),
				small_cpumask_bits, cpumask_check(cpu));
}

/**
 * cpumask_nth_and_andnot - get the Nth cpu set in 1st and 2nd cpumask, and clear in 3rd.
 * @srcp1: the cpumask pointer
+2 −27
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ unsigned long _find_next_bit_le(const unsigned long *addr, unsigned
				long size, unsigned long offset);
#endif

unsigned long find_random_bit(const unsigned long *addr, unsigned long size);

#ifndef find_next_bit
/**
 * find_next_bit - find the next set bit in a memory region
@@ -267,33 +269,6 @@ unsigned long find_nth_and_bit(const unsigned long *addr1, const unsigned long *
	return __find_nth_and_bit(addr1, addr2, size, n);
}

/**
 * find_nth_andnot_bit - find N'th set bit in 2 memory regions,
 *			 flipping bits in 2nd region
 * @addr1: The 1st address to start the search at
 * @addr2: The 2nd address to start the search at
 * @size: The maximum number of bits to search
 * @n: The number of set bit, which position is needed, counting from 0
 *
 * Returns the bit number of the N'th set bit.
 * If no such, returns @size.
 */
static __always_inline
unsigned long find_nth_andnot_bit(const unsigned long *addr1, const unsigned long *addr2,
				unsigned long size, unsigned long n)
{
	if (n >= size)
		return size;

	if (small_const_nbits(size)) {
		unsigned long val =  *addr1 & (~*addr2) & GENMASK(size - 1, 0);

		return val ? fns(val, n) : size;
	}

	return __find_nth_andnot_bit(addr1, addr2, size, n);
}

/**
 * find_nth_and_andnot_bit - find N'th set bit in 2 memory regions,
 *			     excluding those set in 3rd region
+3 −15
Original line number Diff line number Diff line
@@ -492,21 +492,9 @@ static __always_inline int num_node_state(enum node_states state)
static __always_inline int node_random(const nodemask_t *maskp)
{
#if defined(CONFIG_NUMA) && (MAX_NUMNODES > 1)
	int w, bit;

	w = nodes_weight(*maskp);
	switch (w) {
	case 0:
		bit = NUMA_NO_NODE;
		break;
	case 1:
		bit = first_node(*maskp);
		break;
	default:
		bit = find_nth_bit(maskp->bits, MAX_NUMNODES, get_random_u32_below(w));
		break;
	}
	return bit;
	int node = find_random_bit(maskp->bits, MAX_NUMNODES);

	return node < MAX_NUMNODES ? node : NUMA_NO_NODE;
#else
	return 0;
#endif
Loading