diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-01-08 09:26:43 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-01-08 10:35:41 -0500 |
commit | 64af4e0da419ef9e9db0d34a3b5836adbf90a5e8 (patch) | |
tree | e22b8af5c7a2bd592c64b6b4fb6dc8094aa73be1 /tools/lib | |
parent | 552eb975b83756e3d95aeb5edaeb5c3c032b0021 (diff) |
tools lib: Sync tools/lib/find_bit.c with the kernel
Need to move the bitmap.[ch] things from tools/perf/ to tools/lib, will
be done in the next patches.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: George Spelvin <linux@horizon.com
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: Yury Norov <yury.norov@gmail.com>
Link: http://lkml.kernel.org/n/tip-5fys65wkd7gu8j7a7xgukc5t@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/find_bit.c | 103 |
1 files changed, 49 insertions, 54 deletions
diff --git a/tools/lib/find_bit.c b/tools/lib/find_bit.c index 732d8c38d2c3..9122a9e80046 100644 --- a/tools/lib/find_bit.c +++ b/tools/lib/find_bit.c | |||
@@ -1,10 +1,17 @@ | |||
1 | /* find_next_bit.c: fallback find next bit implementation | 1 | /* bit search implementation |
2 | * | 2 | * |
3 | * Copied from lib/find_next_bit.c to tools/lib/find_bit.c | 3 | * Copied from lib/find_bit.c to tools/lib/find_bit.c |
4 | * | 4 | * |
5 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 5 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. |
6 | * Written by David Howells (dhowells@redhat.com) | 6 | * Written by David Howells (dhowells@redhat.com) |
7 | * | 7 | * |
8 | * Copyright (C) 2008 IBM Corporation | ||
9 | * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au> | ||
10 | * (Inspired by David Howell's find_next_bit implementation) | ||
11 | * | ||
12 | * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease | ||
13 | * size and improve performance, 2015. | ||
14 | * | ||
8 | * This program is free software; you can redistribute it and/or | 15 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License | 16 | * modify it under the terms of the GNU General Public License |
10 | * as published by the Free Software Foundation; either version | 17 | * as published by the Free Software Foundation; either version |
@@ -12,52 +19,50 @@ | |||
12 | */ | 19 | */ |
13 | 20 | ||
14 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
15 | #include <asm/types.h> | 22 | #include <linux/bitmap.h> |
16 | #include <asm/byteorder.h> | 23 | #include <linux/kernel.h> |
17 | 24 | ||
18 | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) | 25 | #if !defined(find_next_bit) |
19 | 26 | ||
20 | #ifndef find_next_bit | ||
21 | /* | 27 | /* |
22 | * Find the next set bit in a memory region. | 28 | * This is a common helper function for find_next_bit and |
29 | * find_next_zero_bit. The difference is the "invert" argument, which | ||
30 | * is XORed with each fetched word before searching it for one bits. | ||
23 | */ | 31 | */ |
24 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | 32 | static unsigned long _find_next_bit(const unsigned long *addr, |
25 | unsigned long offset) | 33 | unsigned long nbits, unsigned long start, unsigned long invert) |
26 | { | 34 | { |
27 | const unsigned long *p = addr + BITOP_WORD(offset); | ||
28 | unsigned long result = offset & ~(BITS_PER_LONG-1); | ||
29 | unsigned long tmp; | 35 | unsigned long tmp; |
30 | 36 | ||
31 | if (offset >= size) | 37 | if (!nbits || start >= nbits) |
32 | return size; | 38 | return nbits; |
33 | size -= result; | 39 | |
34 | offset %= BITS_PER_LONG; | 40 | tmp = addr[start / BITS_PER_LONG] ^ invert; |
35 | if (offset) { | 41 | |
36 | tmp = *(p++); | 42 | /* Handle 1st word. */ |
37 | tmp &= (~0UL << offset); | 43 | tmp &= BITMAP_FIRST_WORD_MASK(start); |
38 | if (size < BITS_PER_LONG) | 44 | start = round_down(start, BITS_PER_LONG); |
39 | goto found_first; | 45 | |
40 | if (tmp) | 46 | while (!tmp) { |
41 | goto found_middle; | 47 | start += BITS_PER_LONG; |
42 | size -= BITS_PER_LONG; | 48 | if (start >= nbits) |
43 | result += BITS_PER_LONG; | 49 | return nbits; |
44 | } | 50 | |
45 | while (size & ~(BITS_PER_LONG-1)) { | 51 | tmp = addr[start / BITS_PER_LONG] ^ invert; |
46 | if ((tmp = *(p++))) | ||
47 | goto found_middle; | ||
48 | result += BITS_PER_LONG; | ||
49 | size -= BITS_PER_LONG; | ||
50 | } | 52 | } |
51 | if (!size) | ||
52 | return result; | ||
53 | tmp = *p; | ||
54 | 53 | ||
55 | found_first: | 54 | return min(start + __ffs(tmp), nbits); |
56 | tmp &= (~0UL >> (BITS_PER_LONG - size)); | 55 | } |
57 | if (tmp == 0UL) /* Are any bits set? */ | 56 | #endif |
58 | return result + size; /* Nope. */ | 57 | |
59 | found_middle: | 58 | #ifndef find_next_bit |
60 | return result + __ffs(tmp); | 59 | /* |
60 | * Find the next set bit in a memory region. | ||
61 | */ | ||
62 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | ||
63 | unsigned long offset) | ||
64 | { | ||
65 | return _find_next_bit(addr, size, offset, 0UL); | ||
61 | } | 66 | } |
62 | #endif | 67 | #endif |
63 | 68 | ||
@@ -67,23 +72,13 @@ found_middle: | |||
67 | */ | 72 | */ |
68 | unsigned long find_first_bit(const unsigned long *addr, unsigned long size) | 73 | unsigned long find_first_bit(const unsigned long *addr, unsigned long size) |
69 | { | 74 | { |
70 | const unsigned long *p = addr; | 75 | unsigned long idx; |
71 | unsigned long result = 0; | ||
72 | unsigned long tmp; | ||
73 | 76 | ||
74 | while (size & ~(BITS_PER_LONG-1)) { | 77 | for (idx = 0; idx * BITS_PER_LONG < size; idx++) { |
75 | if ((tmp = *(p++))) | 78 | if (addr[idx]) |
76 | goto found; | 79 | return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); |
77 | result += BITS_PER_LONG; | ||
78 | size -= BITS_PER_LONG; | ||
79 | } | 80 | } |
80 | if (!size) | ||
81 | return result; | ||
82 | 81 | ||
83 | tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); | 82 | return size; |
84 | if (tmp == 0UL) /* Are any bits set? */ | ||
85 | return result + size; /* Nope. */ | ||
86 | found: | ||
87 | return result + __ffs(tmp); | ||
88 | } | 83 | } |
89 | #endif | 84 | #endif |