aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2006-06-27 05:54:51 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-27 20:32:46 -0400
commit77ba89c5cf28d5d98a3cae17f67a3e42b102cc25 (patch)
treed487b536522574ab183cc600b62008c60db85b59 /lib
parent8eb94f80dd2da5977c35cd094f0802c1501a12cd (diff)
[PATCH] pi-futex: add plist implementation
Add the priority-sorted list (plist) implementation. Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig6
-rw-r--r--lib/Makefile1
-rw-r--r--lib/plist.c118
3 files changed, 125 insertions, 0 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index 3de93357f5ab..f6299342b882 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -86,4 +86,10 @@ config TEXTSEARCH_BM
86config TEXTSEARCH_FSM 86config TEXTSEARCH_FSM
87 tristate 87 tristate
88 88
89#
90# plist support is select#ed if needed
91#
92config PLIST
93 boolean
94
89endmenu 95endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 79358ad1f113..10c13c9d7824 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -25,6 +25,7 @@ lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o
25lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o 25lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
26lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o 26lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
27obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o 27obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
28obj-$(CONFIG_PLIST) += plist.o
28obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o 29obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
29 30
30ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 31ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
diff --git a/lib/plist.c b/lib/plist.c
new file mode 100644
index 000000000000..3074a02272f3
--- /dev/null
+++ b/lib/plist.c
@@ -0,0 +1,118 @@
1/*
2 * lib/plist.c
3 *
4 * Descending-priority-sorted double-linked list
5 *
6 * (C) 2002-2003 Intel Corp
7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.
8 *
9 * 2001-2005 (c) MontaVista Software, Inc.
10 * Daniel Walker <dwalker@mvista.com>
11 *
12 * (C) 2005 Thomas Gleixner <tglx@linutronix.de>
13 *
14 * Simplifications of the original code by
15 * Oleg Nesterov <oleg@tv-sign.ru>
16 *
17 * Licensed under the FSF's GNU Public License v2 or later.
18 *
19 * Based on simple lists (include/linux/list.h).
20 *
21 * This file contains the add / del functions which are considered to
22 * be too large to inline. See include/linux/plist.h for further
23 * information.
24 */
25
26#include <linux/plist.h>
27#include <linux/spinlock.h>
28
29#ifdef CONFIG_DEBUG_PI_LIST
30
31static void plist_check_prev_next(struct list_head *t, struct list_head *p,
32 struct list_head *n)
33{
34 if (n->prev != p || p->next != n) {
35 printk("top: %p, n: %p, p: %p\n", t, t->next, t->prev);
36 printk("prev: %p, n: %p, p: %p\n", p, p->next, p->prev);
37 printk("next: %p, n: %p, p: %p\n", n, n->next, n->prev);
38 WARN_ON(1);
39 }
40}
41
42static void plist_check_list(struct list_head *top)
43{
44 struct list_head *prev = top, *next = top->next;
45
46 plist_check_prev_next(top, prev, next);
47 while (next != top) {
48 prev = next;
49 next = prev->next;
50 plist_check_prev_next(top, prev, next);
51 }
52}
53
54static void plist_check_head(struct plist_head *head)
55{
56 WARN_ON(!head->lock);
57 if (head->lock)
58 WARN_ON_SMP(!spin_is_locked(head->lock));
59 plist_check_list(&head->prio_list);
60 plist_check_list(&head->node_list);
61}
62
63#else
64# define plist_check_head(h) do { } while (0)
65#endif
66
67/**
68 * plist_add - add @node to @head
69 *
70 * @node: &struct plist_node pointer
71 * @head: &struct plist_head pointer
72 */
73void plist_add(struct plist_node *node, struct plist_head *head)
74{
75 struct plist_node *iter;
76
77 plist_check_head(head);
78 WARN_ON(!plist_node_empty(node));
79
80 list_for_each_entry(iter, &head->prio_list, plist.prio_list) {
81 if (node->prio < iter->prio)
82 goto lt_prio;
83 else if (node->prio == iter->prio) {
84 iter = list_entry(iter->plist.prio_list.next,
85 struct plist_node, plist.prio_list);
86 goto eq_prio;
87 }
88 }
89
90lt_prio:
91 list_add_tail(&node->plist.prio_list, &iter->plist.prio_list);
92eq_prio:
93 list_add_tail(&node->plist.node_list, &iter->plist.node_list);
94
95 plist_check_head(head);
96}
97
98/**
99 * plist_del - Remove a @node from plist.
100 *
101 * @node: &struct plist_node pointer - entry to be removed
102 * @head: &struct plist_head pointer - list head
103 */
104void plist_del(struct plist_node *node, struct plist_head *head)
105{
106 plist_check_head(head);
107
108 if (!list_empty(&node->plist.prio_list)) {
109 struct plist_node *next = plist_first(&node->plist);
110
111 list_move_tail(&next->plist.prio_list, &node->plist.prio_list);
112 list_del_init(&node->plist.prio_list);
113 }
114
115 list_del_init(&node->plist.node_list);
116
117 plist_check_head(head);
118}