aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/plist.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/lib/plist.c b/lib/plist.c
index 1471988d9190..8c614d0e6c35 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -59,7 +59,8 @@ static void plist_check_head(struct plist_head *head)
59 WARN_ON_SMP(!raw_spin_is_locked(head->rawlock)); 59 WARN_ON_SMP(!raw_spin_is_locked(head->rawlock));
60 if (head->spinlock) 60 if (head->spinlock)
61 WARN_ON_SMP(!spin_is_locked(head->spinlock)); 61 WARN_ON_SMP(!spin_is_locked(head->spinlock));
62 plist_check_list(&head->prio_list); 62 if (!plist_head_empty(head))
63 plist_check_list(&plist_first(head)->prio_list);
63 plist_check_list(&head->node_list); 64 plist_check_list(&head->node_list);
64} 65}
65 66
@@ -75,25 +76,33 @@ static void plist_check_head(struct plist_head *head)
75 */ 76 */
76void plist_add(struct plist_node *node, struct plist_head *head) 77void plist_add(struct plist_node *node, struct plist_head *head)
77{ 78{
78 struct plist_node *iter; 79 struct plist_node *first, *iter, *prev = NULL;
80 struct list_head *node_next = &head->node_list;
79 81
80 plist_check_head(head); 82 plist_check_head(head);
81 WARN_ON(!plist_node_empty(node)); 83 WARN_ON(!plist_node_empty(node));
84 WARN_ON(!list_empty(&node->prio_list));
82 85
83 list_for_each_entry(iter, &head->prio_list, plist.prio_list) { 86 if (plist_head_empty(head))
84 if (node->prio < iter->prio) 87 goto ins_node;
85 goto lt_prio; 88
86 else if (node->prio == iter->prio) { 89 first = iter = plist_first(head);
87 iter = list_entry(iter->plist.prio_list.next, 90
88 struct plist_node, plist.prio_list); 91 do {
89 goto eq_prio; 92 if (node->prio < iter->prio) {
93 node_next = &iter->node_list;
94 break;
90 } 95 }
91 }
92 96
93lt_prio: 97 prev = iter;
94 list_add_tail(&node->plist.prio_list, &iter->plist.prio_list); 98 iter = list_entry(iter->prio_list.next,
95eq_prio: 99 struct plist_node, prio_list);
96 list_add_tail(&node->plist.node_list, &iter->plist.node_list); 100 } while (iter != first);
101
102 if (!prev || prev->prio != node->prio)
103 list_add_tail(&node->prio_list, &iter->prio_list);
104ins_node:
105 list_add_tail(&node->node_list, node_next);
97 106
98 plist_check_head(head); 107 plist_check_head(head);
99} 108}
@@ -108,14 +117,21 @@ void plist_del(struct plist_node *node, struct plist_head *head)
108{ 117{
109 plist_check_head(head); 118 plist_check_head(head);
110 119
111 if (!list_empty(&node->plist.prio_list)) { 120 if (!list_empty(&node->prio_list)) {
112 struct plist_node *next = plist_first(&node->plist); 121 if (node->node_list.next != &head->node_list) {
122 struct plist_node *next;
123
124 next = list_entry(node->node_list.next,
125 struct plist_node, node_list);
113 126
114 list_move_tail(&next->plist.prio_list, &node->plist.prio_list); 127 /* add the next plist_node into prio_list */
115 list_del_init(&node->plist.prio_list); 128 if (list_empty(&next->prio_list))
129 list_add(&next->prio_list, &node->prio_list);
130 }
131 list_del_init(&node->prio_list);
116 } 132 }
117 133
118 list_del_init(&node->plist.node_list); 134 list_del_init(&node->node_list);
119 135
120 plist_check_head(head); 136 plist_check_head(head);
121} 137}