Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 May 2016 12:03:40 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r300496 - in head/sys/compat/linuxkpi/common: include/linux src
Message-ID:  <201605231203.u4NC3eHI010991@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Mon May 23 12:03:40 2016
New Revision: 300496
URL: https://svnweb.freebsd.org/changeset/base/300496

Log:
  Add more list_xxx() functions to the LinuxKPI.
  
  Obtained from:	kmacy @
  MFC after:	1 week
  Sponsored by:	Mellanox Technologies

Modified:
  head/sys/compat/linuxkpi/common/include/linux/list.h
  head/sys/compat/linuxkpi/common/src/linux_compat.c

Modified: head/sys/compat/linuxkpi/common/include/linux/list.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/list.h	Mon May 23 11:57:23 2016	(r300495)
+++ head/sys/compat/linuxkpi/common/include/linux/list.h	Mon May 23 12:03:40 2016	(r300496)
@@ -109,6 +109,13 @@ list_replace(struct list_head *old, stru
 }
 
 static inline void
+list_replace_init(struct list_head *old, struct list_head *new)
+{
+	list_replace(old, new);
+	INIT_LIST_HEAD(old);
+}
+
+static inline void
 linux_list_add(struct list_head *new, struct list_head *prev,
     struct list_head *next)
 {
@@ -132,9 +139,18 @@ list_del_init(struct list_head *entry)
 #define list_first_entry(ptr, type, member) \
         list_entry((ptr)->next, type, member)
 
+#define	list_last_entry(ptr, type, member)	\
+	list_entry((ptr)->prev, type, member)
+
+#define	list_first_entry_or_null(ptr, type, member) \
+	(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+
 #define	list_next_entry(ptr, member)					\
 	list_entry(((ptr)->member.next), typeof(*(ptr)), member)
 
+#define	list_prev_entry(ptr, member)					\
+	list_entry(((ptr)->member.prev), typeof(*(ptr)), member)
+
 #define	list_for_each(p, head)						\
 	for (p = (head)->next; p != (head); p = (p)->next)
 
@@ -436,4 +452,7 @@ static inline int list_is_last(const str
 	     (pos) && ({ n = (pos)->member.next; 1; });			\
 	     pos = hlist_entry_safe(n, typeof(*(pos)), member))
 
+extern void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv,
+    struct list_head *a, struct list_head *b));
+
 #endif /* _LINUX_LIST_H_ */

Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_compat.c	Mon May 23 11:57:23 2016	(r300495)
+++ head/sys/compat/linuxkpi/common/src/linux_compat.c	Mon May 23 12:03:40 2016	(r300496)
@@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
 #include <linux/kernel.h>
+#include <linux/list.h>
 
 #include <vm/vm_pager.h>
 
@@ -1358,6 +1359,47 @@ unregister_inetaddr_notifier(struct noti
         return (0);
 }
 
+struct list_sort_thunk {
+	int (*cmp)(void *, struct list_head *, struct list_head *);
+	void *priv;
+};
+
+static inline int
+linux_le_cmp(void *priv, const void *d1, const void *d2)
+{
+	struct list_head *le1, *le2;
+	struct list_sort_thunk *thunk;
+
+	thunk = priv;
+	le1 = *(__DECONST(struct list_head **, d1));
+	le2 = *(__DECONST(struct list_head **, d2));
+	return ((thunk->cmp)(thunk->priv, le1, le2));
+}
+
+void
+list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv,
+    struct list_head *a, struct list_head *b))
+{
+	struct list_sort_thunk thunk;
+	struct list_head **ar, *le;
+	size_t count, i;
+
+	count = 0;
+	list_for_each(le, head)
+		count++;
+	ar = malloc(sizeof(struct list_head *) * count, M_KMALLOC, M_WAITOK);
+	i = 0;
+	list_for_each(le, head)
+		ar[i++] = le;
+	thunk.cmp = cmp;
+	thunk.priv = priv;
+	qsort_r(ar, count, sizeof(struct list_head *), &thunk, linux_le_cmp);
+	INIT_LIST_HEAD(head);
+	for (i = 0; i < count; i++)
+		list_add_tail(ar[i], head);
+	free(ar, M_KMALLOC);
+}
+
 void
 linux_irq_handler(void *ent)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605231203.u4NC3eHI010991>