diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/plist.c | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/lib/plist.c b/lib/plist.c index 1471988d919..8c614d0e6c3 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 | */ |
76 | void plist_add(struct plist_node *node, struct plist_head *head) | 77 | void 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 | ||
93 | lt_prio: | 97 | prev = iter; |
94 | list_add_tail(&node->plist.prio_list, &iter->plist.prio_list); | 98 | iter = list_entry(iter->prio_list.next, |
95 | eq_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); | ||
104 | ins_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 | } |