Root/
1 | /* |
2 | * A fast, small, non-recursive O(nlog n) sort for the Linux kernel |
3 | * |
4 | * Jan 23 2005 Matt Mackall <mpm@selenic.com> |
5 | */ |
6 | |
7 | #include <linux/kernel.h> |
8 | #include <linux/module.h> |
9 | #include <linux/sort.h> |
10 | #include <linux/slab.h> |
11 | |
12 | static void u32_swap(void *a, void *b, int size) |
13 | { |
14 | u32 t = *(u32 *)a; |
15 | *(u32 *)a = *(u32 *)b; |
16 | *(u32 *)b = t; |
17 | } |
18 | |
19 | static void generic_swap(void *a, void *b, int size) |
20 | { |
21 | char t; |
22 | |
23 | do { |
24 | t = *(char *)a; |
25 | *(char *)a++ = *(char *)b; |
26 | *(char *)b++ = t; |
27 | } while (--size > 0); |
28 | } |
29 | |
30 | /** |
31 | * sort - sort an array of elements |
32 | * @base: pointer to data to sort |
33 | * @num: number of elements |
34 | * @size: size of each element |
35 | * @cmp_func: pointer to comparison function |
36 | * @swap_func: pointer to swap function or NULL |
37 | * |
38 | * This function does a heapsort on the given array. You may provide a |
39 | * swap_func function optimized to your element type. |
40 | * |
41 | * Sorting time is O(n log n) both on average and worst-case. While |
42 | * qsort is about 20% faster on average, it suffers from exploitable |
43 | * O(n*n) worst-case behavior and extra memory requirements that make |
44 | * it less suitable for kernel use. |
45 | */ |
46 | |
47 | void sort(void *base, size_t num, size_t size, |
48 | int (*cmp_func)(const void *, const void *), |
49 | void (*swap_func)(void *, void *, int size)) |
50 | { |
51 | /* pre-scale counters for performance */ |
52 | int i = (num/2 - 1) * size, n = num * size, c, r; |
53 | |
54 | if (!swap_func) |
55 | swap_func = (size == 4 ? u32_swap : generic_swap); |
56 | |
57 | /* heapify */ |
58 | for ( ; i >= 0; i -= size) { |
59 | for (r = i; r * 2 + size < n; r = c) { |
60 | c = r * 2 + size; |
61 | if (c < n - size && |
62 | cmp_func(base + c, base + c + size) < 0) |
63 | c += size; |
64 | if (cmp_func(base + r, base + c) >= 0) |
65 | break; |
66 | swap_func(base + r, base + c, size); |
67 | } |
68 | } |
69 | |
70 | /* sort */ |
71 | for (i = n - size; i > 0; i -= size) { |
72 | swap_func(base, base + i, size); |
73 | for (r = 0; r * 2 + size < i; r = c) { |
74 | c = r * 2 + size; |
75 | if (c < i - size && |
76 | cmp_func(base + c, base + c + size) < 0) |
77 | c += size; |
78 | if (cmp_func(base + r, base + c) >= 0) |
79 | break; |
80 | swap_func(base + r, base + c, size); |
81 | } |
82 | } |
83 | } |
84 | |
85 | EXPORT_SYMBOL(sort); |
86 | |
87 | #if 0 |
88 | /* a simple boot-time regression test */ |
89 | |
90 | int cmpint(const void *a, const void *b) |
91 | { |
92 | return *(int *)a - *(int *)b; |
93 | } |
94 | |
95 | static int sort_test(void) |
96 | { |
97 | int *a, i, r = 1; |
98 | |
99 | a = kmalloc(1000 * sizeof(int), GFP_KERNEL); |
100 | BUG_ON(!a); |
101 | |
102 | printk("testing sort()\n"); |
103 | |
104 | for (i = 0; i < 1000; i++) { |
105 | r = (r * 725861) % 6599; |
106 | a[i] = r; |
107 | } |
108 | |
109 | sort(a, 1000, sizeof(int), cmpint, NULL); |
110 | |
111 | for (i = 0; i < 999; i++) |
112 | if (a[i] > a[i+1]) { |
113 | printk("sort() failed!\n"); |
114 | break; |
115 | } |
116 | |
117 | kfree(a); |
118 | |
119 | return 0; |
120 | } |
121 | |
122 | module_init(sort_test); |
123 | #endif |
124 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9