Commit f0d1b0b30d250a07627ad8b9fbbb5c7cc08422e8
Committed by
Linus Torvalds
1 parent
b3d7ae5f47
[PATCH] LOG2: Implement a general integer log2 facility in the kernel
This facility provides three entry points: ilog2() Log base 2 of unsigned long ilog2_u32() Log base 2 of u32 ilog2_u64() Log base 2 of u64 These facilities can either be used inside functions on dynamic data: int do_something(long q) { ...; y = ilog2(x) ...; } Or can be used to statically initialise global variables with constant values: unsigned n = ilog2(27); When performing static initialisation, the compiler will report "error: initializer element is not constant" if asked to take a log of zero or of something not reducible to a constant. They treat negative numbers as unsigned. When not dealing with a constant, they fall back to using fls() which permits them to use arch-specific log calculation instructions - such as BSR on x86/x86_64 or SCAN on FRV - if available. [akpm@osdl.org: MMC fix] Signed-off-by: David Howells <dhowells@redhat.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: David Howells <dhowells@redhat.com> Cc: Wojtek Kaniewski <wojtekka@toxygen.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 36 changed files with 384 additions and 28 deletions Side-by-side Diff
- arch/alpha/Kconfig
- arch/arm/Kconfig
- arch/arm26/Kconfig
- arch/avr32/Kconfig
- arch/cris/Kconfig
- arch/frv/Kconfig
- arch/h8300/Kconfig
- arch/i386/Kconfig.cpu
- arch/ia64/Kconfig
- arch/m32r/Kconfig
- arch/m68k/Kconfig
- arch/m68knommu/Kconfig
- arch/mips/Kconfig
- arch/parisc/Kconfig
- arch/powerpc/Kconfig
- arch/ppc/Kconfig
- arch/s390/Kconfig
- arch/sh/Kconfig
- arch/sh64/Kconfig
- arch/sparc/Kconfig
- arch/sparc64/Kconfig
- arch/v850/Kconfig
- arch/x86_64/Kconfig
- arch/xtensa/Kconfig
- drivers/infiniband/hw/mthca/mthca_provider.c
- drivers/infiniband/hw/mthca/mthca_qp.c
- drivers/infiniband/hw/mthca/mthca_srq.c
- drivers/infiniband/ulp/iser/iser_memory.c
- drivers/md/dm-crypt.c
- drivers/mmc/tifm_sd.c
- fs/ext2/super.c
- fs/ext3/super.c
- include/asm-frv/bitops.h
- include/linux/kernel.h
- include/linux/log2.h
- mm/page_alloc.c
arch/alpha/Kconfig
arch/arm/Kconfig
arch/arm26/Kconfig
arch/avr32/Kconfig
arch/cris/Kconfig
arch/frv/Kconfig
arch/h8300/Kconfig
arch/i386/Kconfig.cpu
arch/ia64/Kconfig
arch/m32r/Kconfig
arch/m68k/Kconfig
arch/m68knommu/Kconfig
arch/mips/Kconfig
arch/parisc/Kconfig
arch/powerpc/Kconfig
arch/ppc/Kconfig
arch/s390/Kconfig
arch/sh/Kconfig
arch/sh64/Kconfig
arch/sparc/Kconfig
arch/sparc64/Kconfig
arch/v850/Kconfig
arch/x86_64/Kconfig
arch/xtensa/Kconfig
drivers/infiniband/hw/mthca/mthca_provider.c
... | ... | @@ -124,7 +124,7 @@ |
124 | 124 | props->max_map_per_fmr = 255; |
125 | 125 | else |
126 | 126 | props->max_map_per_fmr = |
127 | - (1 << (32 - long_log2(mdev->limits.num_mpts))) - 1; | |
127 | + (1 << (32 - ilog2(mdev->limits.num_mpts))) - 1; | |
128 | 128 | |
129 | 129 | err = 0; |
130 | 130 | out: |
... | ... | @@ -816,7 +816,7 @@ |
816 | 816 | lkey = ucmd.lkey; |
817 | 817 | } |
818 | 818 | |
819 | - ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, long_log2(entries), &status); | |
819 | + ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries), &status); | |
820 | 820 | if (status) |
821 | 821 | ret = -EINVAL; |
822 | 822 |
drivers/infiniband/hw/mthca/mthca_qp.c
... | ... | @@ -636,11 +636,11 @@ |
636 | 636 | |
637 | 637 | if (mthca_is_memfree(dev)) { |
638 | 638 | if (qp->rq.max) |
639 | - qp_context->rq_size_stride = long_log2(qp->rq.max) << 3; | |
639 | + qp_context->rq_size_stride = ilog2(qp->rq.max) << 3; | |
640 | 640 | qp_context->rq_size_stride |= qp->rq.wqe_shift - 4; |
641 | 641 | |
642 | 642 | if (qp->sq.max) |
643 | - qp_context->sq_size_stride = long_log2(qp->sq.max) << 3; | |
643 | + qp_context->sq_size_stride = ilog2(qp->sq.max) << 3; | |
644 | 644 | qp_context->sq_size_stride |= qp->sq.wqe_shift - 4; |
645 | 645 | } |
646 | 646 |
drivers/infiniband/hw/mthca/mthca_srq.c
... | ... | @@ -120,7 +120,7 @@ |
120 | 120 | |
121 | 121 | memset(context, 0, sizeof *context); |
122 | 122 | |
123 | - logsize = long_log2(srq->max); | |
123 | + logsize = ilog2(srq->max); | |
124 | 124 | context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn); |
125 | 125 | context->lkey = cpu_to_be32(srq->mr.ibmr.lkey); |
126 | 126 | context->db_index = cpu_to_be32(srq->db_index); |
... | ... | @@ -213,7 +213,7 @@ |
213 | 213 | if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz)) |
214 | 214 | return -EINVAL; |
215 | 215 | |
216 | - srq->wqe_shift = long_log2(ds); | |
216 | + srq->wqe_shift = ilog2(ds); | |
217 | 217 | |
218 | 218 | srq->srqn = mthca_alloc(&dev->srq_table.alloc); |
219 | 219 | if (srq->srqn == -1) |
drivers/infiniband/ulp/iser/iser_memory.c
... | ... | @@ -114,7 +114,7 @@ |
114 | 114 | |
115 | 115 | if (cmd_data_len > ISER_KMALLOC_THRESHOLD) |
116 | 116 | mem = (void *)__get_free_pages(GFP_NOIO, |
117 | - long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); | |
117 | + ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); | |
118 | 118 | else |
119 | 119 | mem = kmalloc(cmd_data_len, GFP_NOIO); |
120 | 120 | |
... | ... | @@ -211,7 +211,7 @@ |
211 | 211 | |
212 | 212 | if (cmd_data_len > ISER_KMALLOC_THRESHOLD) |
213 | 213 | free_pages((unsigned long)mem_copy->copy_buf, |
214 | - long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); | |
214 | + ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); | |
215 | 215 | else |
216 | 216 | kfree(mem_copy->copy_buf); |
217 | 217 |
drivers/md/dm-crypt.c
... | ... | @@ -220,7 +220,7 @@ |
220 | 220 | const char *opts) |
221 | 221 | { |
222 | 222 | unsigned int bs = crypto_blkcipher_blocksize(cc->tfm); |
223 | - int log = long_log2(bs); | |
223 | + int log = ilog2(bs); | |
224 | 224 | |
225 | 225 | /* we need to calculate how far we must shift the sector count |
226 | 226 | * to get the cipher block count, we use this shift in _gen */ |
drivers/mmc/tifm_sd.c
... | ... | @@ -387,7 +387,7 @@ |
387 | 387 | |
388 | 388 | writel(TIFM_FIFO_INT_SETALL, |
389 | 389 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); |
390 | - writel(long_log2(cmd->data->blksz) - 2, | |
390 | + writel(ilog2(cmd->data->blksz) - 2, | |
391 | 391 | sock->addr + SOCK_FIFO_PAGE_SIZE); |
392 | 392 | writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL); |
393 | 393 | writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); |
fs/ext2/super.c
... | ... | @@ -597,8 +597,6 @@ |
597 | 597 | return 1; |
598 | 598 | } |
599 | 599 | |
600 | -#define log2(n) ffz(~(n)) | |
601 | - | |
602 | 600 | /* |
603 | 601 | * Maximal file size. There is a direct, and {,double-,triple-}indirect |
604 | 602 | * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks. |
605 | 603 | |
... | ... | @@ -834,9 +832,9 @@ |
834 | 832 | sbi->s_sbh = bh; |
835 | 833 | sbi->s_mount_state = le16_to_cpu(es->s_state); |
836 | 834 | sbi->s_addr_per_block_bits = |
837 | - log2 (EXT2_ADDR_PER_BLOCK(sb)); | |
835 | + ilog2 (EXT2_ADDR_PER_BLOCK(sb)); | |
838 | 836 | sbi->s_desc_per_block_bits = |
839 | - log2 (EXT2_DESC_PER_BLOCK(sb)); | |
837 | + ilog2 (EXT2_DESC_PER_BLOCK(sb)); | |
840 | 838 | |
841 | 839 | if (sb->s_magic != EXT2_SUPER_MAGIC) |
842 | 840 | goto cantfind_ext2; |
fs/ext3/super.c
... | ... | @@ -1347,8 +1347,6 @@ |
1347 | 1347 | sb->s_flags = s_flags; /* Restore MS_RDONLY status */ |
1348 | 1348 | } |
1349 | 1349 | |
1350 | -#define log2(n) ffz(~(n)) | |
1351 | - | |
1352 | 1350 | /* |
1353 | 1351 | * Maximal file size. There is a direct, and {,double-,triple-}indirect |
1354 | 1352 | * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks. |
... | ... | @@ -1597,8 +1595,8 @@ |
1597 | 1595 | sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc); |
1598 | 1596 | sbi->s_sbh = bh; |
1599 | 1597 | sbi->s_mount_state = le16_to_cpu(es->s_state); |
1600 | - sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb)); | |
1601 | - sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb)); | |
1598 | + sbi->s_addr_per_block_bits = ilog2(EXT3_ADDR_PER_BLOCK(sb)); | |
1599 | + sbi->s_desc_per_block_bits = ilog2(EXT3_DESC_PER_BLOCK(sb)); | |
1602 | 1600 | for (i=0; i < 4; i++) |
1603 | 1601 | sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); |
1604 | 1602 | sbi->s_def_hash_version = es->s_def_hash_version; |
include/asm-frv/bitops.h
... | ... | @@ -256,6 +256,50 @@ |
256 | 256 | return 31 - bit; |
257 | 257 | } |
258 | 258 | |
259 | +/* | |
260 | + * special slimline version of fls() for calculating ilog2_u32() | |
261 | + * - note: no protection against n == 0 | |
262 | + */ | |
263 | +#define ARCH_HAS_ILOG2_U32 | |
264 | +static inline __attribute__((const)) | |
265 | +int __ilog2_u32(u32 n) | |
266 | +{ | |
267 | + int bit; | |
268 | + asm("scan %1,gr0,%0" : "=r"(bit) : "r"(n)); | |
269 | + return 31 - bit; | |
270 | +} | |
271 | + | |
272 | +/* | |
273 | + * special slimline version of fls64() for calculating ilog2_u64() | |
274 | + * - note: no protection against n == 0 | |
275 | + */ | |
276 | +#define ARCH_HAS_ILOG2_U64 | |
277 | +static inline __attribute__((const)) | |
278 | +int __ilog2_u64(u64 n) | |
279 | +{ | |
280 | + union { | |
281 | + u64 ll; | |
282 | + struct { u32 h, l; }; | |
283 | + } _; | |
284 | + int bit, x, y; | |
285 | + | |
286 | + _.ll = n; | |
287 | + | |
288 | + asm(" subcc %3,gr0,gr0,icc0 \n" | |
289 | + " ckeq icc0,cc4 \n" | |
290 | + " cscan.p %3,gr0,%0 ,cc4,0 \n" | |
291 | + " setlos #63,%1 \n" | |
292 | + " cscan.p %4,gr0,%0 ,cc4,1 \n" | |
293 | + " setlos #31,%2 \n" | |
294 | + " csub.p %1,%0,%0 ,cc4,0 \n" | |
295 | + " csub %2,%0,%0 ,cc4,1 \n" | |
296 | + : "=&r"(bit), "=r"(x), "=r"(y) | |
297 | + : "0r"(_.h), "r"(_.l) | |
298 | + : "icc0", "cc4" | |
299 | + ); | |
300 | + return bit; | |
301 | +} | |
302 | + | |
259 | 303 | #include <asm-generic/bitops/sched.h> |
260 | 304 | #include <asm-generic/bitops/hweight.h> |
261 | 305 |
include/linux/kernel.h
... | ... | @@ -13,6 +13,7 @@ |
13 | 13 | #include <linux/types.h> |
14 | 14 | #include <linux/compiler.h> |
15 | 15 | #include <linux/bitops.h> |
16 | +#include <linux/log2.h> | |
16 | 17 | #include <asm/byteorder.h> |
17 | 18 | #include <asm/bug.h> |
18 | 19 | |
... | ... | @@ -156,14 +157,6 @@ |
156 | 157 | #endif |
157 | 158 | |
158 | 159 | unsigned long int_sqrt(unsigned long); |
159 | - | |
160 | -static inline int __attribute_pure__ long_log2(unsigned long x) | |
161 | -{ | |
162 | - int r = 0; | |
163 | - for (x >>= 1; x > 0; x >>= 1) | |
164 | - r++; | |
165 | - return r; | |
166 | -} | |
167 | 160 | |
168 | 161 | static inline unsigned long |
169 | 162 | __attribute_const__ roundup_pow_of_two(unsigned long x) |
include/linux/log2.h
1 | +/* Integer base 2 logarithm calculation | |
2 | + * | |
3 | + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. | |
4 | + * Written by David Howells (dhowells@redhat.com) | |
5 | + * | |
6 | + * This program is free software; you can redistribute it and/or | |
7 | + * modify it under the terms of the GNU General Public License | |
8 | + * as published by the Free Software Foundation; either version | |
9 | + * 2 of the License, or (at your option) any later version. | |
10 | + */ | |
11 | + | |
12 | +#ifndef _LINUX_LOG2_H | |
13 | +#define _LINUX_LOG2_H | |
14 | + | |
15 | +#include <linux/types.h> | |
16 | +#include <linux/bitops.h> | |
17 | + | |
18 | +/* | |
19 | + * deal with unrepresentable constant logarithms | |
20 | + */ | |
21 | +extern __attribute__((const, noreturn)) | |
22 | +int ____ilog2_NaN(void); | |
23 | + | |
24 | +/* | |
25 | + * non-constant log of base 2 calculators | |
26 | + * - the arch may override these in asm/bitops.h if they can be implemented | |
27 | + * more efficiently than using fls() and fls64() | |
28 | + * - the arch is not required to handle n==0 if implementing the fallback | |
29 | + */ | |
30 | +#ifndef CONFIG_ARCH_HAS_ILOG2_U32 | |
31 | +static inline __attribute__((const)) | |
32 | +int __ilog2_u32(u32 n) | |
33 | +{ | |
34 | + return fls(n) - 1; | |
35 | +} | |
36 | +#endif | |
37 | + | |
38 | +#ifndef CONFIG_ARCH_HAS_ILOG2_U64 | |
39 | +static inline __attribute__((const)) | |
40 | +int __ilog2_u64(u64 n) | |
41 | +{ | |
42 | + return fls64(n) - 1; | |
43 | +} | |
44 | +#endif | |
45 | + | |
46 | +/** | |
47 | + * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value | |
48 | + * @n - parameter | |
49 | + * | |
50 | + * constant-capable log of base 2 calculation | |
51 | + * - this can be used to initialise global variables from constant data, hence | |
52 | + * the massive ternary operator construction | |
53 | + * | |
54 | + * selects the appropriately-sized optimised version depending on sizeof(n) | |
55 | + */ | |
56 | +#define ilog2(n) \ | |
57 | +( \ | |
58 | + __builtin_constant_p(n) ? ( \ | |
59 | + (n) < 1 ? ____ilog2_NaN() : \ | |
60 | + (n) & (1ULL << 63) ? 63 : \ | |
61 | + (n) & (1ULL << 62) ? 62 : \ | |
62 | + (n) & (1ULL << 61) ? 61 : \ | |
63 | + (n) & (1ULL << 60) ? 60 : \ | |
64 | + (n) & (1ULL << 59) ? 59 : \ | |
65 | + (n) & (1ULL << 58) ? 58 : \ | |
66 | + (n) & (1ULL << 57) ? 57 : \ | |
67 | + (n) & (1ULL << 56) ? 56 : \ | |
68 | + (n) & (1ULL << 55) ? 55 : \ | |
69 | + (n) & (1ULL << 54) ? 54 : \ | |
70 | + (n) & (1ULL << 53) ? 53 : \ | |
71 | + (n) & (1ULL << 52) ? 52 : \ | |
72 | + (n) & (1ULL << 51) ? 51 : \ | |
73 | + (n) & (1ULL << 50) ? 50 : \ | |
74 | + (n) & (1ULL << 49) ? 49 : \ | |
75 | + (n) & (1ULL << 48) ? 48 : \ | |
76 | + (n) & (1ULL << 47) ? 47 : \ | |
77 | + (n) & (1ULL << 46) ? 46 : \ | |
78 | + (n) & (1ULL << 45) ? 45 : \ | |
79 | + (n) & (1ULL << 44) ? 44 : \ | |
80 | + (n) & (1ULL << 43) ? 43 : \ | |
81 | + (n) & (1ULL << 42) ? 42 : \ | |
82 | + (n) & (1ULL << 41) ? 41 : \ | |
83 | + (n) & (1ULL << 40) ? 40 : \ | |
84 | + (n) & (1ULL << 39) ? 39 : \ | |
85 | + (n) & (1ULL << 38) ? 38 : \ | |
86 | + (n) & (1ULL << 37) ? 37 : \ | |
87 | + (n) & (1ULL << 36) ? 36 : \ | |
88 | + (n) & (1ULL << 35) ? 35 : \ | |
89 | + (n) & (1ULL << 34) ? 34 : \ | |
90 | + (n) & (1ULL << 33) ? 33 : \ | |
91 | + (n) & (1ULL << 32) ? 32 : \ | |
92 | + (n) & (1ULL << 31) ? 31 : \ | |
93 | + (n) & (1ULL << 30) ? 30 : \ | |
94 | + (n) & (1ULL << 29) ? 29 : \ | |
95 | + (n) & (1ULL << 28) ? 28 : \ | |
96 | + (n) & (1ULL << 27) ? 27 : \ | |
97 | + (n) & (1ULL << 26) ? 26 : \ | |
98 | + (n) & (1ULL << 25) ? 25 : \ | |
99 | + (n) & (1ULL << 24) ? 24 : \ | |
100 | + (n) & (1ULL << 23) ? 23 : \ | |
101 | + (n) & (1ULL << 22) ? 22 : \ | |
102 | + (n) & (1ULL << 21) ? 21 : \ | |
103 | + (n) & (1ULL << 20) ? 20 : \ | |
104 | + (n) & (1ULL << 19) ? 19 : \ | |
105 | + (n) & (1ULL << 18) ? 18 : \ | |
106 | + (n) & (1ULL << 17) ? 17 : \ | |
107 | + (n) & (1ULL << 16) ? 16 : \ | |
108 | + (n) & (1ULL << 15) ? 15 : \ | |
109 | + (n) & (1ULL << 14) ? 14 : \ | |
110 | + (n) & (1ULL << 13) ? 13 : \ | |
111 | + (n) & (1ULL << 12) ? 12 : \ | |
112 | + (n) & (1ULL << 11) ? 11 : \ | |
113 | + (n) & (1ULL << 10) ? 10 : \ | |
114 | + (n) & (1ULL << 9) ? 9 : \ | |
115 | + (n) & (1ULL << 8) ? 8 : \ | |
116 | + (n) & (1ULL << 7) ? 7 : \ | |
117 | + (n) & (1ULL << 6) ? 6 : \ | |
118 | + (n) & (1ULL << 5) ? 5 : \ | |
119 | + (n) & (1ULL << 4) ? 4 : \ | |
120 | + (n) & (1ULL << 3) ? 3 : \ | |
121 | + (n) & (1ULL << 2) ? 2 : \ | |
122 | + (n) & (1ULL << 1) ? 1 : \ | |
123 | + (n) & (1ULL << 0) ? 0 : \ | |
124 | + ____ilog2_NaN() \ | |
125 | + ) : \ | |
126 | + (sizeof(n) <= 4) ? \ | |
127 | + __ilog2_u32(n) : \ | |
128 | + __ilog2_u64(n) \ | |
129 | + ) | |
130 | + | |
131 | +#endif /* _LINUX_LOG2_H */ |
mm/page_alloc.c
... | ... | @@ -3244,7 +3244,7 @@ |
3244 | 3244 | if (numentries > max) |
3245 | 3245 | numentries = max; |
3246 | 3246 | |
3247 | - log2qty = long_log2(numentries); | |
3247 | + log2qty = ilog2(numentries); | |
3248 | 3248 | |
3249 | 3249 | do { |
3250 | 3250 | size = bucketsize << log2qty; |
... | ... | @@ -3266,7 +3266,7 @@ |
3266 | 3266 | printk("%s hash table entries: %d (order: %d, %lu bytes)\n", |
3267 | 3267 | tablename, |
3268 | 3268 | (1U << log2qty), |
3269 | - long_log2(size) - PAGE_SHIFT, | |
3269 | + ilog2(size) - PAGE_SHIFT, | |
3270 | 3270 | size); |
3271 | 3271 | |
3272 | 3272 | if (_hash_shift) |