summaryrefslogtreecommitdiffstats
path: root/tools/lib
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2016-01-08 09:26:43 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-01-08 10:35:41 -0500
commit64af4e0da419ef9e9db0d34a3b5836adbf90a5e8 (patch)
treee22b8af5c7a2bd592c64b6b4fb6dc8094aa73be1 /tools/lib
parent552eb975b83756e3d95aeb5edaeb5c3c032b0021 (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.c103
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 */
24unsigned long find_next_bit(const unsigned long *addr, unsigned long size, 32static 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
55found_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
59found_middle: 58#ifndef find_next_bit
60 return result + __ffs(tmp); 59/*
60 * Find the next set bit in a memory region.
61 */
62unsigned 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 */
68unsigned long find_first_bit(const unsigned long *addr, unsigned long size) 73unsigned 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. */
86found:
87 return result + __ffs(tmp);
88} 83}
89#endif 84#endif