Wed Jul 24 02:55:48 2013 UTC ()
Add linux_list_sort.c implementing list_sort.

Algorithm is merge sort using binary counting in a temporary array of
64 elements on the stack, big enough for any list that'll fit into
memory in a 64-bit address space, but small enough to fit comfortably
on the stack.


(riastradh)
diff -r1.1.2.1 -r1.1.2.2 src/sys/external/bsd/drm2/include/linux/list_sort.h
diff -r0 -r1.1.2.1 src/sys/external/bsd/drm2/linux/linux_list_sort.c
diff -r1.1.2.32 -r1.1.2.33 src/sys/modules/drm2/Makefile

cvs diff -r1.1.2.1 -r1.1.2.2 src/sys/external/bsd/drm2/include/linux/list_sort.h (expand / switch to unified diff)

--- src/sys/external/bsd/drm2/include/linux/list_sort.h 2013/07/24 00:33:12 1.1.2.1
+++ src/sys/external/bsd/drm2/include/linux/list_sort.h 2013/07/24 02:55:48 1.1.2.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: list_sort.h,v 1.1.2.1 2013/07/24 00:33:12 riastradh Exp $ */ 1/* $NetBSD: list_sort.h,v 1.1.2.2 2013/07/24 02:55:48 riastradh Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2013 The NetBSD Foundation, Inc. 4 * Copyright (c) 2013 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Taylor R. Campbell. 8 * by Taylor R. Campbell.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -22,14 +22,19 @@ @@ -22,14 +22,19 @@
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#ifndef _LINUX_LIST_SORT_H_ 32#ifndef _LINUX_LIST_SORT_H_
33#define _LINUX_LIST_SORT_H_ 33#define _LINUX_LIST_SORT_H_
34 34
 35struct list_head;
 36
 37void list_sort(void *, struct list_head *,
 38 int (*)(void *, struct list_head *, struct list_head *));
 39
35#endif /* _LINUX_LIST_SORT_H_ */ 40#endif /* _LINUX_LIST_SORT_H_ */

File Added: src/sys/external/bsd/drm2/linux/linux_list_sort.c
/*	$NetBSD: linux_list_sort.c,v 1.1.2.1 2013/07/24 02:55:48 riastradh Exp $	*/

/*-
 * Copyright (c) 2013 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Taylor R. Campbell.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: linux_list_sort.c,v 1.1.2.1 2013/07/24 02:55:48 riastradh Exp $");

#include <sys/systm.h>

#include <machine/limits.h>

#include <linux/list.h>
#include <linux/list_sort.h>

static struct list_head *
		list_sort_merge(struct list_head *, struct list_head *,
		    int (*)(void *, struct list_head *, struct list_head *),
		    void *);
static void	list_sort_merge_into(struct list_head *,
		    struct list_head *, struct list_head *,
		    int (*)(void *, struct list_head *, struct list_head *),
		    void *);

void
list_sort(void *arg, struct list_head *list,
    int (*compare)(void *, struct list_head *, struct list_head *))
{
	/*
	 * Array of sorted sublists, counting in binary: accumulator[i]
	 * is sorted, and either is NULL or has length 2^i.
	 */
	struct list_head *accumulator[64];

	/* Indices into accumulator.  */
	unsigned int logn, max_logn = 0;

	/* The sorted list we're currently working on.  */
	struct list_head *sorted;

	/* The remainder of the unsorted list.  */
	struct list_head *next;

	/* Make sure we can't possibly have more than 2^64-element lists.  */
	__CTASSERT((CHAR_BIT * sizeof(struct list_head *)) <= 64);

	for (logn = 0; logn < __arraycount(accumulator); logn++)
		accumulator[logn] = NULL;

	list_for_each_safe(sorted, next, list) {
		/* Pick off a single element, always sorted.  */
		sorted->next = NULL;

		/* Add one and propagate the carry.  */
		for (logn = 0; accumulator[logn] != NULL; logn++) {
			/*
			 * Merge, preferring previously accumulated
			 * elements to make the sort stable.
			 */
			sorted = list_sort_merge(accumulator[logn], sorted,
			    compare, arg);
			accumulator[logn] = NULL;
			KASSERT((logn + 1) < __arraycount(accumulator));
		}

		/* Remember the highest index seen so far.  */
		if (logn > max_logn)
			max_logn = logn;

		/*
		 * logn = log_2(length(sorted)), and accumulator[logn]
		 * is now empty, so save the sorted sublist there.
		 */
		accumulator[logn] = sorted;
	}

	/*
	 * Merge ~half of everything we have accumulated.
	 */
	sorted = NULL;
	for (logn = 0; logn < max_logn; logn++)
		sorted = list_sort_merge(accumulator[logn], sorted, compare,
		    arg);

	/*
	 * Merge the last ~halves back into the list, and fix the back
	 * pointers.
	 */
	list_sort_merge_into(list, accumulator[max_logn], sorted, compare,
	    arg);
}

/*
 * Merge the NULL-terminated lists starting at nodes `a' and `b',
 * breaking ties by choosing nodes in `a' first, and returning
 * whichever node has the least element.
 */
static struct list_head *
list_sort_merge(struct list_head *a, struct list_head *b,
    int (*compare)(void *, struct list_head *, struct list_head *), void *arg)
{
	struct list_head head, *tail = &head;

	/*
	 * Merge while elements in both remain.
	 */
	while ((a != NULL) && (b != NULL)) {
		struct list_head **const first = ((*compare)(arg, a, b) <= 0?
		    &a : &b);

		tail = tail->next = *first;
		*first = (*first)->next;
	}

	/*
	 * Attach whatever remains.
	 */
	tail->next = (a != NULL? a : b);
	return head.next;
}

/*
 * Merge the NULL-terminated lists starting at nodes `a' and `b' into
 * the (uninitialized) list head `list', breaking ties by choosing
 * nodes in `a' first, and setting the `prev' pointers as we go.
 */
static void
list_sort_merge_into(struct list_head *list,
    struct list_head *a, struct list_head *b,
    int (*compare)(void *, struct list_head *, struct list_head *), void *arg)
{
	struct list_head *prev = list;

	/*
	 * Merge while elements in both remain.
	 */
	while ((a != NULL) && (b != NULL)) {
		struct list_head **const first = ((*compare)(arg, a, b) <= 0?
		    &a : &b);

		(*first)->prev = prev;
		prev = prev->next = *first;
		*first = (*first)->next;
	}

	/*
	 * Attach whichever of a and b remains, and fix up the prev
	 * pointers all the way down the rest of the list.
	 */
	struct list_head *tail = (a == NULL? b : a);
	while (tail != NULL) {
		prev->next = tail;
		tail->prev = prev;
		prev = prev->next;
		tail = tail->next;
	}

	/*
	 * Finally, finish the cycle.
	 */
	prev->next = list;
	list->prev = prev;
}

cvs diff -r1.1.2.32 -r1.1.2.33 src/sys/modules/drm2/Attic/Makefile (expand / switch to unified diff)

--- src/sys/modules/drm2/Attic/Makefile 2013/07/24 02:55:26 1.1.2.32
+++ src/sys/modules/drm2/Attic/Makefile 2013/07/24 02:55:48 1.1.2.33
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: Makefile,v 1.1.2.32 2013/07/24 02:55:26 riastradh Exp $ 1# $NetBSD: Makefile,v 1.1.2.33 2013/07/24 02:55:48 riastradh Exp $
2 2
3.include "../Makefile.inc" 3.include "../Makefile.inc"
4.include "Makefile.inc" 4.include "Makefile.inc"
5 5
6.PATH: ${S}/external/bsd/drm2/drm 6.PATH: ${S}/external/bsd/drm2/drm
7.PATH: ${S}/external/bsd/drm2/pci 7.PATH: ${S}/external/bsd/drm2/pci
8.PATH: ${S}/external/bsd/drm2/linux 8.PATH: ${S}/external/bsd/drm2/linux
9.PATH: ${S}/external/bsd/drm2/dist/drm 9.PATH: ${S}/external/bsd/drm2/dist/drm
10 10
11KMOD= drm2 11KMOD= drm2
12IOCONF= drm.ioconf 12IOCONF= drm.ioconf
13 13
14#SRCS+= ati_pcigart.c # XXX Restore for ATI support. 14#SRCS+= ati_pcigart.c # XXX Restore for ATI support.
@@ -39,15 +39,16 @@ SRCS+= drm_memory.c @@ -39,15 +39,16 @@ SRCS+= drm_memory.c
39SRCS+= drm_mm.c 39SRCS+= drm_mm.c
40SRCS+= drm_modes.c 40SRCS+= drm_modes.c
41SRCS+= drm_pci.c # XXX Move to drm2pci module later. 41SRCS+= drm_pci.c # XXX Move to drm2pci module later.
42#SRCS+= drm_platform.c # XXX Rewrite per platform. 42#SRCS+= drm_platform.c # XXX Rewrite per platform.
43#SRCS+= drm_prime.c # XXX Revisit later. 43#SRCS+= drm_prime.c # XXX Revisit later.
44#SRCS+= drm_proc.c # XXX Rewrite for sysctl. 44#SRCS+= drm_proc.c # XXX Rewrite for sysctl.
45SRCS+= drm_scatter.c 45SRCS+= drm_scatter.c
46SRCS+= drm_stub.c 46SRCS+= drm_stub.c
47SRCS+= drm_vm.c 47SRCS+= drm_vm.c
48 48
49SRCS+= drm_gem_vm.c 49SRCS+= drm_gem_vm.c
50SRCS+= drm_module.c 50SRCS+= drm_module.c
51SRCS+= linux_idr.c 51SRCS+= linux_idr.c
 52SRCS+= linux_list_sort.c
52 53
53.include <bsd.kmodule.mk> 54.include <bsd.kmodule.mk>