Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 
  This page was automatically generated by the LXR engine.