diff options
Diffstat (limited to 'lib/plist.c')
-rw-r--r-- | lib/plist.c | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/lib/plist.c b/lib/plist.c index 1ebc95f7a46f..d408e774b746 100644 --- a/lib/plist.c +++ b/lib/plist.c | |||
@@ -134,6 +134,46 @@ void plist_del(struct plist_node *node, struct plist_head *head) | |||
134 | plist_check_head(head); | 134 | plist_check_head(head); |
135 | } | 135 | } |
136 | 136 | ||
137 | /** | ||
138 | * plist_requeue - Requeue @node at end of same-prio entries. | ||
139 | * | ||
140 | * This is essentially an optimized plist_del() followed by | ||
141 | * plist_add(). It moves an entry already in the plist to | ||
142 | * after any other same-priority entries. | ||
143 | * | ||
144 | * @node: &struct plist_node pointer - entry to be moved | ||
145 | * @head: &struct plist_head pointer - list head | ||
146 | */ | ||
147 | void plist_requeue(struct plist_node *node, struct plist_head *head) | ||
148 | { | ||
149 | struct plist_node *iter; | ||
150 | struct list_head *node_next = &head->node_list; | ||
151 | |||
152 | plist_check_head(head); | ||
153 | BUG_ON(plist_head_empty(head)); | ||
154 | BUG_ON(plist_node_empty(node)); | ||
155 | |||
156 | if (node == plist_last(head)) | ||
157 | return; | ||
158 | |||
159 | iter = plist_next(node); | ||
160 | |||
161 | if (node->prio != iter->prio) | ||
162 | return; | ||
163 | |||
164 | plist_del(node, head); | ||
165 | |||
166 | plist_for_each_continue(iter, head) { | ||
167 | if (node->prio != iter->prio) { | ||
168 | node_next = &iter->node_list; | ||
169 | break; | ||
170 | } | ||
171 | } | ||
172 | list_add_tail(&node->node_list, node_next); | ||
173 | |||
174 | plist_check_head(head); | ||
175 | } | ||
176 | |||
137 | #ifdef CONFIG_DEBUG_PI_LIST | 177 | #ifdef CONFIG_DEBUG_PI_LIST |
138 | #include <linux/sched.h> | 178 | #include <linux/sched.h> |
139 | #include <linux/module.h> | 179 | #include <linux/module.h> |
@@ -170,12 +210,20 @@ static void __init plist_test_check(int nr_expect) | |||
170 | BUG_ON(prio_pos->prio_list.next != &first->prio_list); | 210 | BUG_ON(prio_pos->prio_list.next != &first->prio_list); |
171 | } | 211 | } |
172 | 212 | ||
213 | static void __init plist_test_requeue(struct plist_node *node) | ||
214 | { | ||
215 | plist_requeue(node, &test_head); | ||
216 | |||
217 | if (node != plist_last(&test_head)) | ||
218 | BUG_ON(node->prio == plist_next(node)->prio); | ||
219 | } | ||
220 | |||
173 | static int __init plist_test(void) | 221 | static int __init plist_test(void) |
174 | { | 222 | { |
175 | int nr_expect = 0, i, loop; | 223 | int nr_expect = 0, i, loop; |
176 | unsigned int r = local_clock(); | 224 | unsigned int r = local_clock(); |
177 | 225 | ||
178 | pr_debug("start plist test\n"); | 226 | printk(KERN_DEBUG "start plist test\n"); |
179 | plist_head_init(&test_head); | 227 | plist_head_init(&test_head); |
180 | for (i = 0; i < ARRAY_SIZE(test_node); i++) | 228 | for (i = 0; i < ARRAY_SIZE(test_node); i++) |
181 | plist_node_init(test_node + i, 0); | 229 | plist_node_init(test_node + i, 0); |
@@ -193,6 +241,10 @@ static int __init plist_test(void) | |||
193 | nr_expect--; | 241 | nr_expect--; |
194 | } | 242 | } |
195 | plist_test_check(nr_expect); | 243 | plist_test_check(nr_expect); |
244 | if (!plist_node_empty(test_node + i)) { | ||
245 | plist_test_requeue(test_node + i); | ||
246 | plist_test_check(nr_expect); | ||
247 | } | ||
196 | } | 248 | } |
197 | 249 | ||
198 | for (i = 0; i < ARRAY_SIZE(test_node); i++) { | 250 | for (i = 0; i < ARRAY_SIZE(test_node); i++) { |
@@ -203,7 +255,7 @@ static int __init plist_test(void) | |||
203 | plist_test_check(nr_expect); | 255 | plist_test_check(nr_expect); |
204 | } | 256 | } |
205 | 257 | ||
206 | pr_debug("end plist test\n"); | 258 | printk(KERN_DEBUG "end plist test\n"); |
207 | return 0; | 259 | return 0; |
208 | } | 260 | } |
209 | 261 | ||