mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-27 04:55:14 +07:00
1e2ad28f80
This patch introduces x86 perf scheduler code helper functions. We need this to later add more complex functionality to support overlapping counter constraints (next patch). The algorithm is modified so that the range of weight values is now generated from the constraints. There shouldn't be other functional changes. With the helper functions the scheduler is controlled. There are functions to initialize, traverse the event list, find unused counters etc. The scheduler keeps its own state. V3: * Added macro for_each_set_bit_cont(). * Changed functions interfaces of perf_sched_find_counter() and perf_sched_next_event() to use bool as return value. * Added some comments to make code better understandable. V4: * Fix broken event assignment if weight of the first event is not wmin (perf_sched_init()). Signed-off-by: Robert Richter <robert.richter@amd.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1321616122-1533-2-git-send-email-robert.richter@amd.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
171 lines
3.9 KiB
C
171 lines
3.9 KiB
C
#ifndef _LINUX_BITOPS_H
|
|
#define _LINUX_BITOPS_H
|
|
#include <asm/types.h>
|
|
|
|
#ifdef __KERNEL__
|
|
#define BIT(nr) (1UL << (nr))
|
|
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
|
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
|
#define BITS_PER_BYTE 8
|
|
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
|
#endif
|
|
|
|
extern unsigned int __sw_hweight8(unsigned int w);
|
|
extern unsigned int __sw_hweight16(unsigned int w);
|
|
extern unsigned int __sw_hweight32(unsigned int w);
|
|
extern unsigned long __sw_hweight64(__u64 w);
|
|
|
|
/*
|
|
* Include this here because some architectures need generic_ffs/fls in
|
|
* scope
|
|
*/
|
|
#include <asm/bitops.h>
|
|
|
|
#define for_each_set_bit(bit, addr, size) \
|
|
for ((bit) = find_first_bit((addr), (size)); \
|
|
(bit) < (size); \
|
|
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
|
|
|
/* same as for_each_set_bit() but use bit as value to start with */
|
|
#define for_each_set_bit_cont(bit, addr, size) \
|
|
for ((bit) = find_next_bit((addr), (size), (bit)); \
|
|
(bit) < (size); \
|
|
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
|
|
|
static __inline__ int get_bitmask_order(unsigned int count)
|
|
{
|
|
int order;
|
|
|
|
order = fls(count);
|
|
return order; /* We could be slightly more clever with -1 here... */
|
|
}
|
|
|
|
static __inline__ int get_count_order(unsigned int count)
|
|
{
|
|
int order;
|
|
|
|
order = fls(count) - 1;
|
|
if (count & (count - 1))
|
|
order++;
|
|
return order;
|
|
}
|
|
|
|
static inline unsigned long hweight_long(unsigned long w)
|
|
{
|
|
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
|
|
}
|
|
|
|
/**
|
|
* rol32 - rotate a 32-bit value left
|
|
* @word: value to rotate
|
|
* @shift: bits to roll
|
|
*/
|
|
static inline __u32 rol32(__u32 word, unsigned int shift)
|
|
{
|
|
return (word << shift) | (word >> (32 - shift));
|
|
}
|
|
|
|
/**
|
|
* ror32 - rotate a 32-bit value right
|
|
* @word: value to rotate
|
|
* @shift: bits to roll
|
|
*/
|
|
static inline __u32 ror32(__u32 word, unsigned int shift)
|
|
{
|
|
return (word >> shift) | (word << (32 - shift));
|
|
}
|
|
|
|
/**
|
|
* rol16 - rotate a 16-bit value left
|
|
* @word: value to rotate
|
|
* @shift: bits to roll
|
|
*/
|
|
static inline __u16 rol16(__u16 word, unsigned int shift)
|
|
{
|
|
return (word << shift) | (word >> (16 - shift));
|
|
}
|
|
|
|
/**
|
|
* ror16 - rotate a 16-bit value right
|
|
* @word: value to rotate
|
|
* @shift: bits to roll
|
|
*/
|
|
static inline __u16 ror16(__u16 word, unsigned int shift)
|
|
{
|
|
return (word >> shift) | (word << (16 - shift));
|
|
}
|
|
|
|
/**
|
|
* rol8 - rotate an 8-bit value left
|
|
* @word: value to rotate
|
|
* @shift: bits to roll
|
|
*/
|
|
static inline __u8 rol8(__u8 word, unsigned int shift)
|
|
{
|
|
return (word << shift) | (word >> (8 - shift));
|
|
}
|
|
|
|
/**
|
|
* ror8 - rotate an 8-bit value right
|
|
* @word: value to rotate
|
|
* @shift: bits to roll
|
|
*/
|
|
static inline __u8 ror8(__u8 word, unsigned int shift)
|
|
{
|
|
return (word >> shift) | (word << (8 - shift));
|
|
}
|
|
|
|
/**
|
|
* sign_extend32 - sign extend a 32-bit value using specified bit as sign-bit
|
|
* @value: value to sign extend
|
|
* @index: 0 based bit index (0<=index<32) to sign bit
|
|
*/
|
|
static inline __s32 sign_extend32(__u32 value, int index)
|
|
{
|
|
__u8 shift = 31 - index;
|
|
return (__s32)(value << shift) >> shift;
|
|
}
|
|
|
|
static inline unsigned fls_long(unsigned long l)
|
|
{
|
|
if (sizeof(l) == 4)
|
|
return fls(l);
|
|
return fls64(l);
|
|
}
|
|
|
|
/**
|
|
* __ffs64 - find first set bit in a 64 bit word
|
|
* @word: The 64 bit word
|
|
*
|
|
* On 64 bit arches this is a synomyn for __ffs
|
|
* The result is not defined if no bits are set, so check that @word
|
|
* is non-zero before calling this.
|
|
*/
|
|
static inline unsigned long __ffs64(u64 word)
|
|
{
|
|
#if BITS_PER_LONG == 32
|
|
if (((u32)word) == 0UL)
|
|
return __ffs((u32)(word >> 32)) + 32;
|
|
#elif BITS_PER_LONG != 64
|
|
#error BITS_PER_LONG not 32 or 64
|
|
#endif
|
|
return __ffs((unsigned long)word);
|
|
}
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#ifndef find_last_bit
|
|
/**
|
|
* find_last_bit - find the last set bit in a memory region
|
|
* @addr: The address to start the search at
|
|
* @size: The maximum size to search
|
|
*
|
|
* Returns the bit number of the first set bit, or size.
|
|
*/
|
|
extern unsigned long find_last_bit(const unsigned long *addr,
|
|
unsigned long size);
|
|
#endif
|
|
|
|
#endif /* __KERNEL__ */
|
|
#endif
|