[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging] lib: move list sorting code



commit 26dfde919cac720c29d076bc8fd38ad0af1b2abb
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Fri Dec 18 13:20:42 2020 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Fri Dec 18 13:20:42 2020 +0100

    lib: move list sorting code
    
    Build the source file always, as by putting it into an archive it still
    won't be linked into final binaries when not needed. This way possible
    build breakage will be easier to notice, and it's more consistent with
    us unconditionally building other library kind of code (e.g. sort() or
    bsearch()).
    
    While moving the source file, take the opportunity and drop the
    pointless EXPORT_SYMBOL() and an unnecessary #include.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Acked-by: Wei Liu <wl@xxxxxxx>
    Reviewed-by: Bertrand Marquis <bertrand.marquis@xxxxxxx>
    Acked-by: Julien Grall <jgrall@xxxxxxxxxx>
---
 xen/arch/arm/Kconfig   |   4 +-
 xen/common/Kconfig     |   3 -
 xen/common/Makefile    |   1 -
 xen/common/list_sort.c | 157 -------------------------------------------------
 xen/lib/Makefile       |   1 +
 xen/lib/list-sort.c    | 155 ++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 157 insertions(+), 164 deletions(-)

diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 41bde2f401..c3eb13ea73 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -56,9 +56,7 @@ config HVM
         def_bool y
 
 config NEW_VGIC
-       bool
-       prompt "Use new VGIC implementation"
-       select NEEDS_LIST_SORT
+       bool "Use new VGIC implementation"
        ---help---
 
        This is an alternative implementation of the ARM GIC interrupt
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 3e2cf25088..0661328a99 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -66,9 +66,6 @@ config MEM_ACCESS
 config NEEDS_LIBELF
        bool
 
-config NEEDS_LIST_SORT
-       bool
-
 menu "Speculative hardening"
 
 config SPECULATIVE_HARDEN_ARRAY
diff --git a/xen/common/Makefile b/xen/common/Makefile
index d109f279a4..332e7d667c 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -21,7 +21,6 @@ obj-y += keyhandler.o
 obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_KEXEC) += kimage.o
 obj-y += lib.o
-obj-$(CONFIG_NEEDS_LIST_SORT) += list_sort.o
 obj-$(CONFIG_LIVEPATCH) += livepatch.o livepatch_elf.o
 obj-$(CONFIG_MEM_ACCESS) += mem_access.o
 obj-y += memory.o
diff --git a/xen/common/list_sort.c b/xen/common/list_sort.c
deleted file mode 100644
index af2b2f6519..0000000000
--- a/xen/common/list_sort.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * list_sort.c: merge sort implementation for linked lists
- * Copied from the Linux kernel (lib/list_sort.c)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <xen/lib.h>
-#include <xen/list.h>
-
-#define MAX_LIST_LENGTH_BITS 20
-
-/*
- * Returns a list organized in an intermediate format suited
- * to chaining of merge() calls: null-terminated, no reserved or
- * sentinel head node, "prev" links not maintained.
- */
-static struct list_head *merge(void *priv,
-                               int (*cmp)(void *priv, struct list_head *a,
-                                       struct list_head *b),
-                               struct list_head *a, struct list_head *b)
-{
-       struct list_head head, *tail = &head;
-
-       while (a && b) {
-               /* if equal, take 'a' -- important for sort stability */
-               if ((*cmp)(priv, a, b) <= 0) {
-                       tail->next = a;
-                       a = a->next;
-               } else {
-                       tail->next = b;
-                       b = b->next;
-               }
-               tail = tail->next;
-       }
-       tail->next = a?:b;
-       return head.next;
-}
-
-/*
- * Combine final list merge with restoration of standard doubly-linked
- * list structure.  This approach duplicates code from merge(), but
- * runs faster than the tidier alternatives of either a separate final
- * prev-link restoration pass, or maintaining the prev links
- * throughout.
- */
-static void merge_and_restore_back_links(void *priv,
-                               int (*cmp)(void *priv, struct list_head *a,
-                                       struct list_head *b),
-                               struct list_head *head,
-                               struct list_head *a, struct list_head *b)
-{
-       struct list_head *tail = head;
-       u8 count = 0;
-
-       while (a && b) {
-               /* if equal, take 'a' -- important for sort stability */
-               if ((*cmp)(priv, a, b) <= 0) {
-                       tail->next = a;
-                       a->prev = tail;
-                       a = a->next;
-               } else {
-                       tail->next = b;
-                       b->prev = tail;
-                       b = b->next;
-               }
-               tail = tail->next;
-       }
-       tail->next = a ? : b;
-
-       do {
-               /*
-                * In worst cases this loop may run many iterations.
-                * Continue callbacks to the client even though no
-                * element comparison is needed, so the client's cmp()
-                * routine can invoke cond_resched() periodically.
-                */
-               if (unlikely(!(++count)))
-                       (*cmp)(priv, tail->next, tail->next);
-
-               tail->next->prev = tail;
-               tail = tail->next;
-       } while (tail->next);
-
-       tail->next = head;
-       head->prev = tail;
-}
-
-/**
- * list_sort - sort a list
- * @priv: private data, opaque to list_sort(), passed to @cmp
- * @head: the list to sort
- * @cmp: the elements comparison function
- *
- * This function implements "merge sort", which has O(nlog(n))
- * complexity.
- *
- * The comparison function @cmp must return a negative value if @a
- * should sort before @b, and a positive value if @a should sort after
- * @b. If @a and @b are equivalent, and their original relative
- * ordering is to be preserved, @cmp must return 0.
- */
-void list_sort(void *priv, struct list_head *head,
-               int (*cmp)(void *priv, struct list_head *a,
-                       struct list_head *b))
-{
-       struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
-                                               -- last slot is a sentinel */
-       int lev;  /* index into part[] */
-       int max_lev = 0;
-       struct list_head *list;
-
-       if (list_empty(head))
-               return;
-
-       memset(part, 0, sizeof(part));
-
-       head->prev->next = NULL;
-       list = head->next;
-
-       while (list) {
-               struct list_head *cur = list;
-               list = list->next;
-               cur->next = NULL;
-
-               for (lev = 0; part[lev]; lev++) {
-                       cur = merge(priv, cmp, part[lev], cur);
-                       part[lev] = NULL;
-               }
-               if (lev > max_lev) {
-                       if (unlikely(lev >= ARRAY_SIZE(part)-1)) {
-                               dprintk(XENLOG_DEBUG,
-                                       "list too long for efficiency\n");
-                               lev--;
-                       }
-                       max_lev = lev;
-               }
-               part[lev] = cur;
-       }
-
-       for (lev = 0; lev < max_lev; lev++)
-               if (part[lev])
-                       list = merge(priv, cmp, part[lev], list);
-
-       merge_and_restore_back_links(priv, cmp, head, part[max_lev], list);
-}
-EXPORT_SYMBOL(list_sort);
diff --git a/xen/lib/Makefile b/xen/lib/Makefile
index b8814361d6..764f3624b5 100644
--- a/xen/lib/Makefile
+++ b/xen/lib/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_X86) += x86/
 
 lib-y += ctype.o
+lib-y += list-sort.o
diff --git a/xen/lib/list-sort.c b/xen/lib/list-sort.c
new file mode 100644
index 0000000000..f8d8bbf281
--- /dev/null
+++ b/xen/lib/list-sort.c
@@ -0,0 +1,155 @@
+/*
+ * list_sort.c: merge sort implementation for linked lists
+ * Copied from the Linux kernel (lib/list_sort.c)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/list.h>
+
+#define MAX_LIST_LENGTH_BITS 20
+
+/*
+ * Returns a list organized in an intermediate format suited
+ * to chaining of merge() calls: null-terminated, no reserved or
+ * sentinel head node, "prev" links not maintained.
+ */
+static struct list_head *merge(void *priv,
+                               int (*cmp)(void *priv, struct list_head *a,
+                                       struct list_head *b),
+                               struct list_head *a, struct list_head *b)
+{
+       struct list_head head, *tail = &head;
+
+       while (a && b) {
+               /* if equal, take 'a' -- important for sort stability */
+               if ((*cmp)(priv, a, b) <= 0) {
+                       tail->next = a;
+                       a = a->next;
+               } else {
+                       tail->next = b;
+                       b = b->next;
+               }
+               tail = tail->next;
+       }
+       tail->next = a?:b;
+       return head.next;
+}
+
+/*
+ * Combine final list merge with restoration of standard doubly-linked
+ * list structure.  This approach duplicates code from merge(), but
+ * runs faster than the tidier alternatives of either a separate final
+ * prev-link restoration pass, or maintaining the prev links
+ * throughout.
+ */
+static void merge_and_restore_back_links(void *priv,
+                               int (*cmp)(void *priv, struct list_head *a,
+                                       struct list_head *b),
+                               struct list_head *head,
+                               struct list_head *a, struct list_head *b)
+{
+       struct list_head *tail = head;
+       u8 count = 0;
+
+       while (a && b) {
+               /* if equal, take 'a' -- important for sort stability */
+               if ((*cmp)(priv, a, b) <= 0) {
+                       tail->next = a;
+                       a->prev = tail;
+                       a = a->next;
+               } else {
+                       tail->next = b;
+                       b->prev = tail;
+                       b = b->next;
+               }
+               tail = tail->next;
+       }
+       tail->next = a ? : b;
+
+       do {
+               /*
+                * In worst cases this loop may run many iterations.
+                * Continue callbacks to the client even though no
+                * element comparison is needed, so the client's cmp()
+                * routine can invoke cond_resched() periodically.
+                */
+               if (unlikely(!(++count)))
+                       (*cmp)(priv, tail->next, tail->next);
+
+               tail->next->prev = tail;
+               tail = tail->next;
+       } while (tail->next);
+
+       tail->next = head;
+       head->prev = tail;
+}
+
+/**
+ * list_sort - sort a list
+ * @priv: private data, opaque to list_sort(), passed to @cmp
+ * @head: the list to sort
+ * @cmp: the elements comparison function
+ *
+ * This function implements "merge sort", which has O(nlog(n))
+ * complexity.
+ *
+ * The comparison function @cmp must return a negative value if @a
+ * should sort before @b, and a positive value if @a should sort after
+ * @b. If @a and @b are equivalent, and their original relative
+ * ordering is to be preserved, @cmp must return 0.
+ */
+void list_sort(void *priv, struct list_head *head,
+               int (*cmp)(void *priv, struct list_head *a,
+                       struct list_head *b))
+{
+       struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
+                                               -- last slot is a sentinel */
+       int lev;  /* index into part[] */
+       int max_lev = 0;
+       struct list_head *list;
+
+       if (list_empty(head))
+               return;
+
+       memset(part, 0, sizeof(part));
+
+       head->prev->next = NULL;
+       list = head->next;
+
+       while (list) {
+               struct list_head *cur = list;
+               list = list->next;
+               cur->next = NULL;
+
+               for (lev = 0; part[lev]; lev++) {
+                       cur = merge(priv, cmp, part[lev], cur);
+                       part[lev] = NULL;
+               }
+               if (lev > max_lev) {
+                       if (unlikely(lev >= ARRAY_SIZE(part)-1)) {
+                               dprintk(XENLOG_DEBUG,
+                                       "list too long for efficiency\n");
+                               lev--;
+                       }
+                       max_lev = lev;
+               }
+               part[lev] = cur;
+       }
+
+       for (lev = 0; lev < max_lev; lev++)
+               if (part[lev])
+                       list = merge(priv, cmp, part[lev], list);
+
+       merge_and_restore_back_links(priv, cmp, head, part[max_lev], list);
+}
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.