diff options
author | Ingo Molnar <mingo@elte.hu> | 2006-06-27 05:54:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-27 20:32:46 -0400 |
commit | 77ba89c5cf28d5d98a3cae17f67a3e42b102cc25 (patch) | |
tree | d487b536522574ab183cc600b62008c60db85b59 /include | |
parent | 8eb94f80dd2da5977c35cd094f0802c1501a12cd (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 'include')
-rw-r--r-- | include/linux/plist.h | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/include/linux/plist.h b/include/linux/plist.h new file mode 100644 index 000000000000..3404faef542c --- /dev/null +++ b/include/linux/plist.h | |||
@@ -0,0 +1,247 @@ | |||
1 | /* | ||
2 | * Descending-priority-sorted double-linked list | ||
3 | * | ||
4 | * (C) 2002-2003 Intel Corp | ||
5 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>. | ||
6 | * | ||
7 | * 2001-2005 (c) MontaVista Software, Inc. | ||
8 | * Daniel Walker <dwalker@mvista.com> | ||
9 | * | ||
10 | * (C) 2005 Thomas Gleixner <tglx@linutronix.de> | ||
11 | * | ||
12 | * Simplifications of the original code by | ||
13 | * Oleg Nesterov <oleg@tv-sign.ru> | ||
14 | * | ||
15 | * Licensed under the FSF's GNU Public License v2 or later. | ||
16 | * | ||
17 | * Based on simple lists (include/linux/list.h). | ||
18 | * | ||
19 | * This is a priority-sorted list of nodes; each node has a | ||
20 | * priority from INT_MIN (highest) to INT_MAX (lowest). | ||
21 | * | ||
22 | * Addition is O(K), removal is O(1), change of priority of a node is | ||
23 | * O(K) and K is the number of RT priority levels used in the system. | ||
24 | * (1 <= K <= 99) | ||
25 | * | ||
26 | * This list is really a list of lists: | ||
27 | * | ||
28 | * - The tier 1 list is the prio_list, different priority nodes. | ||
29 | * | ||
30 | * - The tier 2 list is the node_list, serialized nodes. | ||
31 | * | ||
32 | * Simple ASCII art explanation: | ||
33 | * | ||
34 | * |HEAD | | ||
35 | * | | | ||
36 | * |prio_list.prev|<------------------------------------| | ||
37 | * |prio_list.next|<->|pl|<->|pl|<--------------->|pl|<-| | ||
38 | * |10 | |10| |21| |21| |21| |40| (prio) | ||
39 | * | | | | | | | | | | | | | ||
40 | * | | | | | | | | | | | | | ||
41 | * |node_list.next|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| | ||
42 | * |node_list.prev|<------------------------------------| | ||
43 | * | ||
44 | * The nodes on the prio_list list are sorted by priority to simplify | ||
45 | * the insertion of new nodes. There are no nodes with duplicate | ||
46 | * priorites on the list. | ||
47 | * | ||
48 | * The nodes on the node_list is ordered by priority and can contain | ||
49 | * entries which have the same priority. Those entries are ordered | ||
50 | * FIFO | ||
51 | * | ||
52 | * Addition means: look for the prio_list node in the prio_list | ||
53 | * for the priority of the node and insert it before the node_list | ||
54 | * entry of the next prio_list node. If it is the first node of | ||
55 | * that priority, add it to the prio_list in the right position and | ||
56 | * insert it into the serialized node_list list | ||
57 | * | ||
58 | * Removal means remove it from the node_list and remove it from | ||
59 | * the prio_list if the node_list list_head is non empty. In case | ||
60 | * of removal from the prio_list it must be checked whether other | ||
61 | * entries of the same priority are on the list or not. If there | ||
62 | * is another entry of the same priority then this entry has to | ||
63 | * replace the removed entry on the prio_list. If the entry which | ||
64 | * is removed is the only entry of this priority then a simple | ||
65 | * remove from both list is sufficient. | ||
66 | * | ||
67 | * INT_MIN is the highest priority, 0 is the medium highest, INT_MAX | ||
68 | * is lowest priority. | ||
69 | * | ||
70 | * No locking is done, up to the caller. | ||
71 | * | ||
72 | */ | ||
73 | #ifndef _LINUX_PLIST_H_ | ||
74 | #define _LINUX_PLIST_H_ | ||
75 | |||
76 | #include <linux/list.h> | ||
77 | #include <linux/spinlock_types.h> | ||
78 | |||
79 | struct plist_head { | ||
80 | struct list_head prio_list; | ||
81 | struct list_head node_list; | ||
82 | #ifdef CONFIG_DEBUG_PI_LIST | ||
83 | spinlock_t *lock; | ||
84 | #endif | ||
85 | }; | ||
86 | |||
87 | struct plist_node { | ||
88 | int prio; | ||
89 | struct plist_head plist; | ||
90 | }; | ||
91 | |||
92 | #ifdef CONFIG_DEBUG_PI_LIST | ||
93 | # define PLIST_HEAD_LOCK_INIT(_lock) .lock = _lock | ||
94 | #else | ||
95 | # define PLIST_HEAD_LOCK_INIT(_lock) | ||
96 | #endif | ||
97 | |||
98 | /** | ||
99 | * #PLIST_HEAD_INIT - static struct plist_head initializer | ||
100 | * | ||
101 | * @head: struct plist_head variable name | ||
102 | */ | ||
103 | #define PLIST_HEAD_INIT(head, _lock) \ | ||
104 | { \ | ||
105 | .prio_list = LIST_HEAD_INIT((head).prio_list), \ | ||
106 | .node_list = LIST_HEAD_INIT((head).node_list), \ | ||
107 | PLIST_HEAD_LOCK_INIT(&(_lock)) \ | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * #PLIST_NODE_INIT - static struct plist_node initializer | ||
112 | * | ||
113 | * @node: struct plist_node variable name | ||
114 | * @__prio: initial node priority | ||
115 | */ | ||
116 | #define PLIST_NODE_INIT(node, __prio) \ | ||
117 | { \ | ||
118 | .prio = (__prio), \ | ||
119 | .plist = PLIST_HEAD_INIT((node).plist, NULL), \ | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * plist_head_init - dynamic struct plist_head initializer | ||
124 | * | ||
125 | * @head: &struct plist_head pointer | ||
126 | */ | ||
127 | static inline void | ||
128 | plist_head_init(struct plist_head *head, spinlock_t *lock) | ||
129 | { | ||
130 | INIT_LIST_HEAD(&head->prio_list); | ||
131 | INIT_LIST_HEAD(&head->node_list); | ||
132 | #ifdef CONFIG_DEBUG_PI_LIST | ||
133 | head->lock = lock; | ||
134 | #endif | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * plist_node_init - Dynamic struct plist_node initializer | ||
139 | * | ||
140 | * @node: &struct plist_node pointer | ||
141 | * @prio: initial node priority | ||
142 | */ | ||
143 | static inline void plist_node_init(struct plist_node *node, int prio) | ||
144 | { | ||
145 | node->prio = prio; | ||
146 | plist_head_init(&node->plist, NULL); | ||
147 | } | ||
148 | |||
149 | extern void plist_add(struct plist_node *node, struct plist_head *head); | ||
150 | extern void plist_del(struct plist_node *node, struct plist_head *head); | ||
151 | |||
152 | /** | ||
153 | * plist_for_each - iterate over the plist | ||
154 | * | ||
155 | * @pos1: the type * to use as a loop counter. | ||
156 | * @head: the head for your list. | ||
157 | */ | ||
158 | #define plist_for_each(pos, head) \ | ||
159 | list_for_each_entry(pos, &(head)->node_list, plist.node_list) | ||
160 | |||
161 | /** | ||
162 | * plist_for_each_entry_safe - iterate over a plist of given type safe | ||
163 | * against removal of list entry | ||
164 | * | ||
165 | * @pos1: the type * to use as a loop counter. | ||
166 | * @n1: another type * to use as temporary storage | ||
167 | * @head: the head for your list. | ||
168 | */ | ||
169 | #define plist_for_each_safe(pos, n, head) \ | ||
170 | list_for_each_entry_safe(pos, n, &(head)->node_list, plist.node_list) | ||
171 | |||
172 | /** | ||
173 | * plist_for_each_entry - iterate over list of given type | ||
174 | * | ||
175 | * @pos: the type * to use as a loop counter. | ||
176 | * @head: the head for your list. | ||
177 | * @member: the name of the list_struct within the struct. | ||
178 | */ | ||
179 | #define plist_for_each_entry(pos, head, mem) \ | ||
180 | list_for_each_entry(pos, &(head)->node_list, mem.plist.node_list) | ||
181 | |||
182 | /** | ||
183 | * plist_for_each_entry_safe - iterate over list of given type safe against | ||
184 | * removal of list entry | ||
185 | * | ||
186 | * @pos: the type * to use as a loop counter. | ||
187 | * @n: another type * to use as temporary storage | ||
188 | * @head: the head for your list. | ||
189 | * @m: the name of the list_struct within the struct. | ||
190 | */ | ||
191 | #define plist_for_each_entry_safe(pos, n, head, m) \ | ||
192 | list_for_each_entry_safe(pos, n, &(head)->node_list, m.plist.node_list) | ||
193 | |||
194 | /** | ||
195 | * plist_head_empty - return !0 if a plist_head is empty | ||
196 | * | ||
197 | * @head: &struct plist_head pointer | ||
198 | */ | ||
199 | static inline int plist_head_empty(const struct plist_head *head) | ||
200 | { | ||
201 | return list_empty(&head->node_list); | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * plist_node_empty - return !0 if plist_node is not on a list | ||
206 | * | ||
207 | * @node: &struct plist_node pointer | ||
208 | */ | ||
209 | static inline int plist_node_empty(const struct plist_node *node) | ||
210 | { | ||
211 | return plist_head_empty(&node->plist); | ||
212 | } | ||
213 | |||
214 | /* All functions below assume the plist_head is not empty. */ | ||
215 | |||
216 | /** | ||
217 | * plist_first_entry - get the struct for the first entry | ||
218 | * | ||
219 | * @ptr: the &struct plist_head pointer. | ||
220 | * @type: the type of the struct this is embedded in. | ||
221 | * @member: the name of the list_struct within the struct. | ||
222 | */ | ||
223 | #ifdef CONFIG_DEBUG_PI_LIST | ||
224 | # define plist_first_entry(head, type, member) \ | ||
225 | ({ \ | ||
226 | WARN_ON(plist_head_empty(head)); \ | ||
227 | container_of(plist_first(head), type, member); \ | ||
228 | }) | ||
229 | #else | ||
230 | # define plist_first_entry(head, type, member) \ | ||
231 | container_of(plist_first(head), type, member) | ||
232 | #endif | ||
233 | |||
234 | /** | ||
235 | * plist_first - return the first node (and thus, highest priority) | ||
236 | * | ||
237 | * @head: the &struct plist_head pointer | ||
238 | * | ||
239 | * Assumes the plist is _not_ empty. | ||
240 | */ | ||
241 | static inline struct plist_node* plist_first(const struct plist_head *head) | ||
242 | { | ||
243 | return list_entry(head->node_list.next, | ||
244 | struct plist_node, plist.node_list); | ||
245 | } | ||
246 | |||
247 | #endif | ||