aboutsummaryrefslogtreecommitdiffstats
path: root/lib/sort.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sort.c')
-rw-r--r--lib/sort.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/lib/sort.c b/lib/sort.c
index 43c9fe73ae2e..fc20df42aa6f 100644
--- a/lib/sort.c
+++ b/lib/sort.c
@@ -8,6 +8,12 @@
8#include <linux/export.h> 8#include <linux/export.h>
9#include <linux/sort.h> 9#include <linux/sort.h>
10 10
11static int alignment_ok(const void *base, int align)
12{
13 return IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ||
14 ((unsigned long)base & (align - 1)) == 0;
15}
16
11static void u32_swap(void *a, void *b, int size) 17static void u32_swap(void *a, void *b, int size)
12{ 18{
13 u32 t = *(u32 *)a; 19 u32 t = *(u32 *)a;
@@ -15,6 +21,13 @@ static void u32_swap(void *a, void *b, int size)
15 *(u32 *)b = t; 21 *(u32 *)b = t;
16} 22}
17 23
24static void u64_swap(void *a, void *b, int size)
25{
26 u64 t = *(u64 *)a;
27 *(u64 *)a = *(u64 *)b;
28 *(u64 *)b = t;
29}
30
18static void generic_swap(void *a, void *b, int size) 31static void generic_swap(void *a, void *b, int size)
19{ 32{
20 char t; 33 char t;
@@ -50,8 +63,14 @@ void sort(void *base, size_t num, size_t size,
50 /* pre-scale counters for performance */ 63 /* pre-scale counters for performance */
51 int i = (num/2 - 1) * size, n = num * size, c, r; 64 int i = (num/2 - 1) * size, n = num * size, c, r;
52 65
53 if (!swap_func) 66 if (!swap_func) {
54 swap_func = (size == 4 ? u32_swap : generic_swap); 67 if (size == 4 && alignment_ok(base, 4))
68 swap_func = u32_swap;
69 else if (size == 8 && alignment_ok(base, 8))
70 swap_func = u64_swap;
71 else
72 swap_func = generic_swap;
73 }
55 74
56 /* heapify */ 75 /* heapify */
57 for ( ; i >= 0; i -= size) { 76 for ( ; i >= 0; i -= size) {