|
@@ -8,6 +8,12 @@
|
|
#include <linux/export.h>
|
|
#include <linux/export.h>
|
|
#include <linux/sort.h>
|
|
#include <linux/sort.h>
|
|
|
|
|
|
|
|
+static int alignment_ok(const void *base, int align)
|
|
|
|
+{
|
|
|
|
+ return IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ||
|
|
|
|
+ ((unsigned long)base & (align - 1)) == 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static void u32_swap(void *a, void *b, int size)
|
|
static void u32_swap(void *a, void *b, int size)
|
|
{
|
|
{
|
|
u32 t = *(u32 *)a;
|
|
u32 t = *(u32 *)a;
|
|
@@ -15,6 +21,13 @@ static void u32_swap(void *a, void *b, int size)
|
|
*(u32 *)b = t;
|
|
*(u32 *)b = t;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void u64_swap(void *a, void *b, int size)
|
|
|
|
+{
|
|
|
|
+ u64 t = *(u64 *)a;
|
|
|
|
+ *(u64 *)a = *(u64 *)b;
|
|
|
|
+ *(u64 *)b = t;
|
|
|
|
+}
|
|
|
|
+
|
|
static void generic_swap(void *a, void *b, int size)
|
|
static void generic_swap(void *a, void *b, int size)
|
|
{
|
|
{
|
|
char t;
|
|
char t;
|
|
@@ -50,8 +63,14 @@ void sort(void *base, size_t num, size_t size,
|
|
/* pre-scale counters for performance */
|
|
/* pre-scale counters for performance */
|
|
int i = (num/2 - 1) * size, n = num * size, c, r;
|
|
int i = (num/2 - 1) * size, n = num * size, c, r;
|
|
|
|
|
|
- if (!swap_func)
|
|
|
|
- swap_func = (size == 4 ? u32_swap : generic_swap);
|
|
|
|
|
|
+ if (!swap_func) {
|
|
|
|
+ if (size == 4 && alignment_ok(base, 4))
|
|
|
|
+ swap_func = u32_swap;
|
|
|
|
+ else if (size == 8 && alignment_ok(base, 8))
|
|
|
|
+ swap_func = u64_swap;
|
|
|
|
+ else
|
|
|
|
+ swap_func = generic_swap;
|
|
|
|
+ }
|
|
|
|
|
|
/* heapify */
|
|
/* heapify */
|
|
for ( ; i >= 0; i -= size) {
|
|
for ( ; i >= 0; i -= size) {
|