Blame view

tools/perf/util/include/linux/bitops.h 3.79 KB
5a116dd27   Frederic Weisbecker   perf tools: Use k...
1
2
  #ifndef _PERF_LINUX_BITOPS_H_
  #define _PERF_LINUX_BITOPS_H_
fb72014d9   Arnaldo Carvalho de Melo   perf tools: Don't...
3
  #include <linux/kernel.h>
a860a6081   Arnaldo Carvalho de Melo   perf tools: Add m...
4
  #include <linux/compiler.h>
fb72014d9   Arnaldo Carvalho de Melo   perf tools: Don't...
5
  #include <asm/hweight.h>
5a116dd27   Frederic Weisbecker   perf tools: Use k...
6

3f34f6c02   Irina Tirdea   perf tools: inclu...
7
8
9
  #ifndef __WORDSIZE
  #define __WORDSIZE (__SIZEOF_LONG__ * 8)
  #endif
fb72014d9   Arnaldo Carvalho de Melo   perf tools: Don't...
10
11
12
  #define BITS_PER_LONG __WORDSIZE
  #define BITS_PER_BYTE           8
  #define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
80c0120a3   David Ahern   perf tools: Fix e...
13
14
  #define BITS_TO_U64(nr)         DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
  #define BITS_TO_U32(nr)         DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
15268138e   Sukadev Bhattiprolu   perf tools: Fix P...
15
  #define BITS_TO_BYTES(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE)
416c419cc   Jiri Olsa   perf tools: Add t...
16
17
  #define BIT_WORD(nr)            ((nr) / BITS_PER_LONG)
  #define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_LONG))
ee3d25044   Paul Mackerras   perf tools: Fix c...
18

b1e5a9bee   Robert Richter   perf tools: Use f...
19
20
21
22
23
24
  #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 */
307b1cd7e   Akinobu Mita   bitops: rename fo...
25
  #define for_each_set_bit_from(bit, addr, size) \
b1e5a9bee   Robert Richter   perf tools: Use f...
26
27
28
  	for ((bit) = find_next_bit((addr), (size), (bit));	\
  	     (bit) < (size);					\
  	     (bit) = find_next_bit((addr), (size), (bit) + 1))
5a116dd27   Frederic Weisbecker   perf tools: Use k...
29
30
31
32
  static inline void set_bit(int nr, unsigned long *addr)
  {
  	addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
  }
baa2f6ced   Arnaldo Carvalho de Melo   perf record: Add ...
33
34
35
36
  static inline void clear_bit(int nr, unsigned long *addr)
  {
  	addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
  }
5a116dd27   Frederic Weisbecker   perf tools: Use k...
37
38
39
40
41
  static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
  {
  	return ((1UL << (nr % BITS_PER_LONG)) &
  		(((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
  }
fb72014d9   Arnaldo Carvalho de Melo   perf tools: Don't...
42
43
44
45
  static inline unsigned long hweight_long(unsigned long w)
  {
  	return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
  }
5a116dd27   Frederic Weisbecker   perf tools: Use k...
46

b1e5a9bee   Robert Richter   perf tools: Use f...
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  #define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)
  
  /**
   * __ffs - find first bit in word.
   * @word: The word to search
   *
   * Undefined if no bit exists, so code should check against 0 first.
   */
  static __always_inline unsigned long __ffs(unsigned long word)
  {
  	int num = 0;
  
  #if BITS_PER_LONG == 64
  	if ((word & 0xffffffff) == 0) {
  		num += 32;
  		word >>= 32;
  	}
  #endif
  	if ((word & 0xffff) == 0) {
  		num += 16;
  		word >>= 16;
  	}
  	if ((word & 0xff) == 0) {
  		num += 8;
  		word >>= 8;
  	}
  	if ((word & 0xf) == 0) {
  		num += 4;
  		word >>= 4;
  	}
  	if ((word & 0x3) == 0) {
  		num += 2;
  		word >>= 2;
  	}
  	if ((word & 0x1) == 0)
  		num += 1;
  	return num;
  }
b39c2a57a   Jiri Olsa   perf tools: Fix s...
85
  typedef const unsigned long __attribute__((__may_alias__)) long_alias_t;
b1e5a9bee   Robert Richter   perf tools: Use f...
86
87
88
89
90
91
  /*
   * Find the first set bit in a memory region.
   */
  static inline unsigned long
  find_first_bit(const unsigned long *addr, unsigned long size)
  {
b39c2a57a   Jiri Olsa   perf tools: Fix s...
92
  	long_alias_t *p = (long_alias_t *) addr;
b1e5a9bee   Robert Richter   perf tools: Use f...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  	unsigned long result = 0;
  	unsigned long tmp;
  
  	while (size & ~(BITS_PER_LONG-1)) {
  		if ((tmp = *(p++)))
  			goto found;
  		result += BITS_PER_LONG;
  		size -= BITS_PER_LONG;
  	}
  	if (!size)
  		return result;
  
  	tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
  	if (tmp == 0UL)		/* Are any bits set? */
  		return result + size;	/* Nope. */
  found:
  	return result + __ffs(tmp);
  }
  
  /*
   * Find the next set bit in a memory region.
   */
  static inline unsigned long
  find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
  {
  	const unsigned long *p = addr + BITOP_WORD(offset);
  	unsigned long result = offset & ~(BITS_PER_LONG-1);
  	unsigned long tmp;
  
  	if (offset >= size)
  		return size;
  	size -= result;
  	offset %= BITS_PER_LONG;
  	if (offset) {
  		tmp = *(p++);
  		tmp &= (~0UL << offset);
  		if (size < BITS_PER_LONG)
  			goto found_first;
  		if (tmp)
  			goto found_middle;
  		size -= BITS_PER_LONG;
  		result += BITS_PER_LONG;
  	}
  	while (size & ~(BITS_PER_LONG-1)) {
  		if ((tmp = *(p++)))
  			goto found_middle;
  		result += BITS_PER_LONG;
  		size -= BITS_PER_LONG;
  	}
  	if (!size)
  		return result;
  	tmp = *p;
  
  found_first:
  	tmp &= (~0UL >> (BITS_PER_LONG - size));
  	if (tmp == 0UL)		/* Are any bits set? */
  		return result + size;	/* Nope. */
  found_middle:
  	return result + __ffs(tmp);
  }
5a116dd27   Frederic Weisbecker   perf tools: Use k...
153
  #endif